Příkazy iterace (referenční příručka jazyka C#)

Následující příkazy opakovaně spouští příkaz nebo blok příkazů:

  • Příkaz for : provede tělo, zatímco se zadaný logický výraz vyhodnotí jako true .
  • Příkaz foreach : vytvoří výčet prvků kolekce a provede její tělo pro každý prvek kolekce.
  • Příkaz do : podmíněně provede tělo jednou nebo vícekrát.
  • Příkaz while : podmíněně provede tělo nulakrát nebo vícekrát.

V jakémkoli bodě v těle iteračního příkazu můžete přerušit smyčku pomocí příkazu break nebo krokovat na další iteraci ve smyčce pomocí příkazu continue.

Příkaz for

Příkaz spustí příkaz nebo blok příkazů, zatímco se zadaný logický for výraz vyhodnotí jako true . Následující příklad ukazuje příkaz , který provádí jeho tělo, zatímco čítač celého čísla for je menší než tři:

for (int i = 0; i < 3; i++)
{
    Console.Write(i);
}
// Output:
// 012

Předchozí příklad ukazuje prvky for příkazu :

  • Oddíl inicializátoru, který se provede pouze jednou před vstupem do smyčky. Obvykle deklarujete a inicializujete proměnnou místní smyčky v této části. Deklarovaná proměnná není přístupná z vnějšku for příkazu .

    Oddíl inicializátoru v předchozím příkladu deklaruje a inicializuje celočíselnou proměnnou čítače:

    int i = 0
    
  • Oddíl podmínky, který určuje, jestli se má provést další iterace ve smyčce. Pokud se vyhodnotí jako nebo není k dispozici, provede se další true iterace. V opačném případě se smyčka ukončí. Oddíl condition musí být logický výraz.

    Oddíl podmínky v předchozím příkladu zkontroluje, jestli je hodnota čítače menší než tři:

    i < 3
    
  • Oddíl iterátoru, který definuje, co se stane po každém spuštění těla smyčky.

    Oddíl iterátoru v předchozím příkladu zvýší čítač:

    i++
    
  • Tělo smyčky, což musí být příkaz nebo blok příkazů.

Oddíl iterátoru může obsahovat nula nebo více následujících výrazů příkazu oddělených čárkami:

Pokud nedeklarujete proměnnou smyčky v oddílu inicializátoru, můžete také použít nula nebo více výrazů z předchozího seznamu v části inicializátoru. Následující příklad ukazuje několik méně častých použití oddílů inicializátoru a iterátoru: přiřazení hodnoty externí proměnné v oddílu inicializátoru, vyvolání metody v oddílech inicializátoru a iterátoru a změna hodnot dvou proměnných v oddílu iterátoru:

int i;
int j = 3;
for (i = 0, Console.WriteLine($"Start: i={i}, j={j}"); i < j; i++, j--, Console.WriteLine($"Step: i={i}, j={j}"))
{
    //...
}
// Output:
// Start: i=0, j=3
// Step: i=1, j=2
// Step: i=2, j=1

Všechny části příkazu for jsou volitelné. Například následující kód definuje nekonečnou for smyčku:

for ( ; ; )
{
    //...
}

Příkaz foreach

Příkaz spustí příkaz nebo blok příkazů pro každý prvek v instanci typu, který implementuje rozhraní nebo , jak ukazuje foreach System.Collections.IEnumerable následující System.Collections.Generic.IEnumerable<T> příklad:

var fibNumbers = new List<int> { 0, 1, 1, 2, 3, 5, 8, 13 };
foreach (int element in fibNumbers)
{
    Console.Write($"{element} ");
}
// Output:
// 0 1 1 2 3 5 8 13

Příkaz foreach není omezen na tyto typy. Můžete ji použít s instancí libovolného typu, která splňuje následující podmínky:

  • Typ má veřejnou metodu bez GetEnumerator parametrů. Počínaje jazykem C# 9.0 může být metoda rozšiřující metodou GetEnumerator typu.
  • Návratový typ metody má veřejnou vlastnost a veřejnou metodu GetEnumerator Current bez parametrů, jejíž MoveNext návratový typ je bool .

Následující příklad používá příkaz s instancí typu foreach System.Span<T> , která neimplementuje žádná rozhraní:

Span<int> numbers = new int[] { 3, 14, 15, 92, 6 };
foreach (int number in numbers)
{
    Console.Write($"{number} ");
}
// Output:
// 3 14 15 92 6

Počínaje jazykem C# 7.3, pokud vlastnost enumerátoru vrací návratovou hodnotu odkazu ( kde je typ elementu kolekce), můžete deklarovat iterační proměnnou s modifikátorem nebo , jak ukazuje následující Current ref T T ref ref readonly příklad:

Span<int> storage = stackalloc int[10];
int num = 0;
foreach (ref int item in storage)
{
    item = num++;
}
foreach (ref readonly var item in storage)
{
    Console.Write($"{item} ");
}
// Output:
// 0 1 2 3 4 5 6 7 8 9

Pokud je foreach příkaz použit na , je null NullReferenceException vyvolána. Pokud je zdrojová kolekce příkazu prázdná, tělo příkazu se nespouště a foreach foreach přeskočí.

await foreach

Počínaje jazykem C# 8.0 můžete pomocí příkazu využívat asynchronní datový proud, to znamená typ kolekce, která await foreach implementuje IAsyncEnumerable<T> rozhraní. Každá iterace smyčky může být pozastavena, zatímco se další prvek načítá asynchronně. Následující příklad ukazuje, jak použít await foreach příkaz :

await foreach (var item in GenerateSequenceAsync())
{
    Console.WriteLine(item);
}

Příkaz můžete použít await foreach také s instancí libovolného typu, která splňuje následující podmínky:

  • Typ má veřejnou metodu bez GetAsyncEnumerator parametrů. Tato metoda může být rozšiřující metodou typu.
  • Návratový typ metody má veřejnou vlastnost a veřejnou metodu bez parametrů, jejíž návratový typ je , nebo jakýkoli jiný typ awaitable, jehož metoda GetAsyncEnumerator Current MoveNextAsync Task<bool> ValueTask<bool> awaiter GetResult vrací bool hodnotu.

Ve výchozím nastavení jsou prvky datového proudu zpracovány v zachyceného kontextu. Pokud chcete zakázat zachytávání kontextu, použijte TaskAsyncEnumerableExtensions.ConfigureAwait rozšiřující metodu . Další informace o kontextech synchronizace a zachycení aktuálního kontextu najdete v tématu Využívání asynchronního vzoru založeného na úlohách. Další informace o asynchronních datových proudech najdete v části Asynchronní datové proudy článku Co je nového v C# 8.0.

Typ iterační proměnné

Pomocí klíčového var slova můžete kompilátoru nechat odvodit typ iterační proměnné v příkazu foreach , jak ukazuje následující kód:

foreach (var item in collection) { }

Můžete také explicitně zadat typ iterační proměnné, jak ukazuje následující kód:

IEnumerable<T> collection = new T[5];
foreach (V item in collection) { }

V předchozím formuláři musí být typ elementu kolekce implicitně nebo explicitně T převoditelný na typ V iterační proměnné. Pokud explicitní převod z T na V selže za běhu, vyvolá příkaz foreach InvalidCastException . Pokud je například T nezapečetěný typ třídy, může být libovolný typ rozhraní, dokonce i ten, který V T neimplementuje. Za běhu může být typ elementu kolekce ten, který je odvozen od a T ve skutečnosti implementuje V . Pokud tomu tak není, vyvolá InvalidCastException se .

Příkaz do

Příkaz spustí příkaz nebo blok příkazů, zatímco se zadaný logický do výraz vyhodnotí jako true . Vzhledem k tomu, že se tento výraz vyhodnocuje po každém spuštění smyčky, smyčka do se provede jednou nebo vícekrát. To se liší od smyčky while, která se provádí nulakrát nebo vícekrát.

Následující příklad ukazuje použití do příkazu :

int n = 0;
do
{
    Console.Write(n);
    n++;
} while (n < 5);
// Output:
// 01234

Příkaz while

Příkaz spustí příkaz nebo blok příkazů, zatímco se zadaný logický while výraz vyhodnotí jako true . Vzhledem k tomu, že se tento výraz vyhodnocuje před každým spuštěním smyčky, smyčka while se provede nulakrát nebo vícekrát. To se liší od smyčky provádění, která se provádí jednou nebo vícekrát.

Následující příklad ukazuje použití while příkazu :

int n = 0;
while (n < 5)
{
    Console.Write(n);
    n++;
}
// Output:
// 01234

specifikace jazyka C#

Další informace najdete v následujících částech specifikace jazyka C#:

Další informace o funkcích přidaných v jazyce C# 8.0 a novějších najdete v následujících poznámkách k návrhu funkcí:

Viz také