Iterační příkazy

Tip

Tento článek je součástí části Základy pro vývojáře, kteří už znají aspoň jeden programovací jazyk a učí se jazyk C#. Pokud s programováním teprve začínáte, začněte nejprve kurzy Začínáme . Kompletní syntaxi najdete v referenční dokumentaci k jazyku v části iterační příkazy.

Pochází z jiného jazyka? Všechny čtyři smyčky jazyka C# (foreach, while,do-while a for) mají přímé ekvivalenty v Java, C++ a JavaScriptu. Nejčastěji používáte foreach . Iteruje kolekci bez indexu, podobně jako rozšířený for v Javě nebo for...of v JavaScriptu.

Příkazy iterace spouští blok kódu opakovaně. Každý průchod blokem je iterace a opakující se blok je smyčka. Jazyk C# poskytuje čtyři smyčky. Začněte s foreach pro kolekce, používejte while a do-while, když opakování řídí podmínka, a for použijte, když potřebujete explicitní index.

Iterace kolekce pomocí foreach

Příkaz foreach spustí jeho tělo jednou pro každý prvek v kolekci v pořadí. Je to nejběžnější volba pro čtení kolekce, protože nespravujete index ani kontrolu hranic. Tento foreach příkaz zabraňuje typickým chybám off-by-one:

string[] names = ["Ana", "Ben", "Cleo"];

// foreach reads each element in order. It's the default loop for
// collections: no index to manage and no off-by-one mistakes.
foreach (string name in names)
{
    Console.WriteLine(name); // => Ana, then Ben, then Cleo
}

foreach funguje s libovolným typem, který jazyk C# rozpozná jako posloupnost, včetně polí, List<T>a Dictionary<TKey,TValue>. Proměnná iterace (name v předchozím příkladu) je jen pro čtení, takže ji nemůžete znovu přiřadit uvnitř smyčky.

Tělo smyčky je jeden příkaz, například přiřazení nebo volání metody. Blokový příkaz je sám o sobě jediným příkazem, který uzavírá nula nebo více příkazů ve složených závorkách ({ }).

Mnoho kódovacích standardů doporučuje uzavřít tělo smyčky do složených závorek, a to i pro jeden příkaz. Složené závorky jednoznačně vymezují rozsah platnosti. Zabrání běžné chybě: později přidáte druhý řádek, u kterého očekáváte, že se spustí při každé iteraci, ale místo toho se po skončení smyčky spustí jen jednou. Pouze složené závorky rozhodují, které příkazy patří do smyčky. C# nepovažuje bílé znaky za významné, takže samotné odsazení nikdy nemá význam. Složené závorky jsou přípustné i kolem jediného řádku: blok je jediný příkaz, který smyčka opakuje. Odsazujte kód kvůli přehlednosti, ale blok vymezujte pomocí složených závorek.

Opakovat, dokud platí podmínka while

Smyčka while kontroluje svou logickou podmínku před každou iterací. Pokud je false podmínka na začátku, tělo se nikdy nespustí, takže smyčka while se spustí nulou nebo vícekrát:

int countdown = 3;

// A while loop checks its condition before each iteration, so the body
// runs zero or more times.
while (countdown > 0)
{
    Console.WriteLine(countdown); // => 3, then 2, then 1
    countdown--;
}

Ujistěte se, že něco uvnitř smyčky mění podmínku. V předchozím příkladu countdown-- nakonec nastaví podmínku false. Smyčka, jejíž podmínka nikdy nenabude hodnoty false, běží donekonečna.

Spusťte blok alespoň jednou pomocí do-while

Smyčka do-while kontroluje její stav po každé iteraci, takže tělo vždy běží alespoň jednou. Použijte ho, když se musí provést první průchod před vyhodnocením podmínky, jako je například výzva k zadání vstupu a jeho ověření:

int attempts = 0;

// A do-while loop runs its body once, then checks the condition. Use it
// when the body must run at least one time.
do
{
    attempts++;
    Console.WriteLine($"Attempt {attempts}"); // => Attempt 1, then Attempt 2, then Attempt 3
}
while (attempts < 3);

Počítat s for

Příkaz for smyčky obsahuje tři části: inicializátor , který se spouští jednou před smyčkou, podmínku , která se kontroluje před každou iterací, a iterátor , který se spustí po každé iteraci. Použijte for , když potřebujete samotný index, nejen prvky. Index obvykle potřebujete, pokud chcete upravit prvek, a nečíst jeho hodnotu.

// A for loop fits when you need an explicit index. The three parts are
// the initializer, the condition, and the iterator.
for (int i = 0; i < 3; i++)
{
    Console.WriteLine(i); // => 0, then 1, then 2
}

Při čtení pouze prvků, pokud nepoužíváte pozice nebo přiřazujete nové hodnoty, preferujte foreach. Uvádí záměr jasněji a vyhne se aritmetickému indexu.

Ukončete nebo přeskočte pomocí break a continue

Dva skokové příkazy vám umožňují přesnější řízení v rámci libovolné smyčky. Příkaz break okamžitě ukončí smyčku a přeskočí všechny zbývající iterace:

int[] numbers = [2, 4, 7, 8];

// break stops the loop immediately, skipping any remaining elements.
foreach (int number in numbers)
{
    if (number % 2 != 0)
    {
        Console.WriteLine($"First odd number: {number}"); // => First odd number: 7
        break;
    }
}

Příkaz continue přeskočí zbytek aktuální iterace a přejde na další:

int[] values = [1, 2, 3, 4, 5];

// continue skips the rest of the current iteration and moves to the next.
foreach (int value in values)
{
    if (value % 2 == 0)
    {
        continue; // skip even numbers
    }

    Console.WriteLine(value); // => 1, then 3, then 5
}

Iterace asynchronního datového proudu pomocí await foreach

Asynchronní datový proud je čtenář, který používá asynchronní úlohu k vytvoření každého dalšího prvku. Jazyk C# ho představuje s rozhraním IAsyncEnumerable<T> . Data, která dorazí v průběhu času, jako jsou stránky z webového rozhraní API nebo řádků z databáze, odpovídají tomuto modelu: načtení dalšího prvku je očekávaná operace místo okamžitého návratu.

Chcete-li využívat asynchronní datový proud, vložte await klíčové slovo před foreach. Každá iterace vyčkává na další prvek, takže se běh smyčky pozastaví, než je tento prvek vygenerován, namísto blokování vlákna:

private static async Task AwaitForeachExample()
{
    // await foreach consumes an asynchronous stream. Each iteration can
    // suspend while the next element is produced.
    await foreach (int value in GenerateAsync())
    {
        Console.WriteLine(value); // => 0, then 1, then 2
    }
}

private static async IAsyncEnumerable<int> GenerateAsync()
{
    for (int i = 0; i < 3; i++)
    {
        await Task.Delay(1); // stand-in for real asynchronous work
        yield return i;
    }
}

Asynchronní datové proudy jsou založeny na async a await. Úplný návod najdete v tématu Generování a využívání asynchronních datových proudů.

Viz také