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í jakotrue. - 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
forpříkazu .Oddíl inicializátoru v předchozím příkladu deklaruje a inicializuje celočíselnou proměnnou čítače:
int i = 0Oddí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ší
trueiterace. 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 < 3Oddí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:
- prefix nebo postfix increment expression, například
++ineboi++ - prefix nebo postfix decrement expression, například
--ineboi-- - Přiřazení
- Vyvolání metody
- await – výraz
- Vytvoření objektu pomocí nového operátoru
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
GetEnumeratorparametrů. Počínaje jazykem C# 9.0 může být metoda rozšiřující metodouGetEnumeratortypu. - Návratový typ metody má veřejnou vlastnost a veřejnou metodu
GetEnumeratorCurrentbez parametrů, jejížMoveNextnávratový typ jebool.
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
GetAsyncEnumeratorparametrů. 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
GetAsyncEnumeratorCurrentMoveNextAsyncTask<bool>ValueTask<bool>awaiterGetResultvracíboolhodnotu.
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í: