Instrukcje iteracji — for
, , foreach
do
iwhile
Instrukcje iteracji wielokrotnie wykonują instrukcję lub blok instrukcji. Instrukcja for
wykonuje jego treść, podczas gdy określone wyrażenie logiczne daje wartość true
. Instrukcja foreach
wylicza elementy kolekcji i wykonuje jej treść dla każdego elementu kolekcji. Instrukcja do
warunkowo wykonuje treść co najmniej raz. Instrukcja while
warunkowo wykonuje treść zero lub więcej razy.
W dowolnym momencie w treści instrukcji iteracji można wyprowadzić pętlę przy użyciu instrukcji break
. Możesz przejść do następnej iteracji w pętli przy użyciu instrukcji continue
.
Instrukcja for
Instrukcja for
wykonuje instrukcję lub blok instrukcji, podczas gdy określone wyrażenie logiczne oblicza wartość true
. W poniższym przykładzie pokazano instrukcję for
, która wykonuje jego treść, a licznik liczby całkowitej jest mniejszy niż trzy:
for (int i = 0; i < 3; i++)
{
Console.Write(i);
}
// Output:
// 012
W poprzednim przykładzie przedstawiono elementy instrukcji for
:
Sekcja inicjatora wykonywana tylko raz przed wejściem do pętli. Zazwyczaj deklarujesz i inicjujesz lokalną zmienną pętli w tej sekcji. Nie można uzyskać dostępu do zadeklarowanej zmiennej spoza instrukcji
for
.Sekcja inicjatora w poprzednim przykładzie deklaruje i inicjuje zmienną licznika liczb całkowitych:
int i = 0
Sekcja warunku określająca, czy należy wykonać następną iterację w pętli. Jeśli zostanie obliczona wartość
true
lub nie jest obecna, zostanie wykonana następna iteracja. W przeciwnym razie pętla zostanie zakończona. Sekcja warunku musi być wyrażeniem logicznym.Sekcja warunku w poprzednim przykładzie sprawdza, czy wartość licznika jest mniejsza niż trzy:
i < 3
Sekcja iteratora, która definiuje, co się dzieje po każdym wykonaniu treści pętli.
Sekcja iteratora w poprzednim przykładzie zwiększa licznik:
i++
Treść pętli, która musi być instrukcją lub blokiem instrukcji.
Sekcja iteratora może zawierać zero lub więcej z następujących wyrażeń instrukcji rozdzielonych przecinkami:
- prefiks lub wyrażenie przyrostka przyrostkowego, takie jak
++i
lubi++
- wyrażenie dekrementacji prefiksu lub postfiksu, na przykład
--i
lubi--
- Przypisania
- wywołanie metody
await
Wyrażenie- tworzenie obiektu przy użyciu
new
operatora
Jeśli nie deklarujesz zmiennej pętli w sekcji inicjatora, możesz również użyć zera lub większej liczby wyrażeń z poprzedniej listy w sekcji inicjatora. W poniższym przykładzie pokazano kilka mniej typowych użycia sekcji inicjatora i iteratora: przypisywanie wartości do zmiennej zewnętrznej w sekcji inicjatora, wywoływanie metody w sekcjach inicjatora i iteratora oraz zmienianie wartości dwóch zmiennych w sekcji iteratora:
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
Wszystkie sekcje instrukcji for
są opcjonalne. Na przykład poniższy kod definiuje pętlę nieskończoną for
:
for ( ; ; )
{
//...
}
Instrukcja foreach
Instrukcja foreach
wykonuje instrukcję lub blok instrukcji dla każdego elementu w wystąpieniu typu implementujący System.Collections.IEnumerable interfejs lub System.Collections.Generic.IEnumerable<T> , jak pokazano w poniższym przykładzie:
List<int> fibNumbers = new() { 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
Instrukcja nie jest ograniczona foreach
do tych typów. Można go używać z wystąpieniem dowolnego typu, które spełnia następujące warunki:
- Typ ma publiczną metodę bez
GetEnumerator
parametrów. MetodaGetEnumerator
może być metodą rozszerzenia typu. - Zwracany
GetEnumerator
typ metody ma właściwość publicznąCurrent
i publiczną metodę bezMoveNext
parametrów, której zwracany typ tobool
.
W poniższym przykładzie użyto instrukcji foreach
z wystąpieniem System.Span<T> typu, które nie implementuje żadnych interfejsów:
Span<int> numbers = [3, 14, 15, 92, 6];
foreach (int number in numbers)
{
Console.Write($"{number} ");
}
// Output:
// 3 14 15 92 6
Jeśli właściwość modułu Current
wyliczającego zwraca wartość zwracaną przez odwołanie (ref T
gdzie T
jest typem elementu kolekcji), można zadeklarować zmienną iteracji za pomocą ref
modyfikatora lubref readonly
, jak pokazano w poniższym przykładzie:
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
Jeśli kolekcja źródłowa instrukcji foreach
jest pusta, treść instrukcji foreach
nie jest wykonywana i pomijana. Jeśli instrukcja zostanie zastosowana foreach
do null
metody , NullReferenceException zostanie zgłoszony element .
await foreach
Możesz użyć instrukcji await foreach
, aby użyć asynchronicznego strumienia danych, czyli typu kolekcji, który implementuje IAsyncEnumerable<T> interfejs. Każda iteracja pętli może być zawieszona, gdy następny element jest pobierany asynchronicznie. W poniższym przykładzie pokazano, jak używać instrukcji await foreach
:
await foreach (var item in GenerateSequenceAsync())
{
Console.WriteLine(item);
}
Można również użyć instrukcji await foreach
z wystąpieniem dowolnego typu, które spełnia następujące warunki:
- Typ ma publiczną metodę bez
GetAsyncEnumerator
parametrów. Ta metoda może być metodą rozszerzenia typu. - Zwracany typ
GetAsyncEnumerator
metody ma właściwość publicznąCurrent
i publiczną metodę bezMoveNextAsync
parametrów, której zwracany typ toTask<bool>
,ValueTask<bool>
lub dowolny inny oczekiwany typ, którego metoda awaiterGetResult
zwracabool
wartość.
Domyślnie elementy strumienia są przetwarzane w przechwyconym kontekście. Jeśli chcesz wyłączyć przechwytywanie kontekstu, użyj TaskAsyncEnumerableExtensions.ConfigureAwait metody rozszerzenia. Aby uzyskać więcej informacji na temat kontekstów synchronizacji i przechwytywania bieżącego kontekstu, zobacz Korzystanie ze wzorca asynchronicznego opartego na zadaniach. Aby uzyskać więcej informacji na temat strumieni asynchronicznych, zobacz samouczek dotyczący strumieni asynchronicznych.
Typ zmiennej iteracji
Słowo kluczowe umożliwia var
kompilatorowi wnioskowanie typu zmiennej iteracji w instrukcji, jak pokazano w foreach
poniższym kodzie:
foreach (var item in collection) { }
Uwaga
var
Typ elementu może być wywnioskowany przez kompilator jako typ odwołania dopuszczalny do wartości null, w zależności od tego, czy kontekst obsługujący wartość null jest włączony i czy typ wyrażenia inicjalizacji jest typem odwołania.
Aby uzyskać więcej informacji, zobacz Niejawnie typizowane zmienne lokalne.
Można również jawnie określić typ zmiennej iteracji, jak pokazano w poniższym kodzie:
IEnumerable<T> collection = new T[5];
foreach (V item in collection) { }
W poprzednim formularzu typ T
elementu kolekcji musi być niejawnie lub jawnie konwertowany na typ V
zmiennej iteracji. Jeśli jawna konwersja z T
do V
kończy się niepowodzeniem w czasie wykonywania, foreach
instrukcja zgłasza błąd InvalidCastException. Na przykład jeśli T
jest typem klasy niezatieczętowanej, V
może być dowolny typ interfejsu, nawet ten, który T
nie implementuje. W czasie wykonywania typ elementu kolekcji może być tym, z którego pochodzi T
element, a w rzeczywistości implementuje V
element . Jeśli tak nie jest, InvalidCastException jest zgłaszany.
Instrukcja do
Instrukcja do
wykonuje instrukcję lub blok instrukcji, podczas gdy określone wyrażenie logiczne oblicza wartość true
. Ponieważ to wyrażenie jest obliczane po każdym wykonaniu pętli, pętla do
wykonuje co najmniej jeden raz. Pętla do
różni się od while
pętli, która wykonuje zero lub więcej razy.
W poniższym przykładzie pokazano użycie instrukcji do
:
int n = 0;
do
{
Console.Write(n);
n++;
} while (n < 5);
// Output:
// 01234
Instrukcja while
Instrukcja while
wykonuje instrukcję lub blok instrukcji, podczas gdy określone wyrażenie logiczne oblicza wartość true
. Ponieważ to wyrażenie jest oceniane przed każdym wykonaniem pętli, pętla while
wykonuje zero lub więcej razy. Pętla while
różni się od do
pętli, która wykonuje co najmniej jeden raz.
W poniższym przykładzie pokazano użycie instrukcji while
:
int n = 0;
while (n < 5)
{
Console.Write(n);
n++;
}
// Output:
// 01234
specyfikacja języka C#
Aby uzyskać więcej informacji, zobacz następujące sekcje specyfikacji języka C#:
Aby uzyskać więcej informacji na temat tych funkcji, zobacz następujące uwagi dotyczące propozycji funkcji: