Instrukcje iteracji — for, , foreachdoiwhile

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 = [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. Metoda GetEnumerator może być metodą rozszerzenia typu.
  • Zwracany GetEnumerator typ metody ma właściwość publiczną Current i publiczną metodę bez MoveNext parametrów, której zwracany typ to bool.

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 nullmetody , 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ę bez MoveNextAsync parametrów, której zwracany typ to Task<bool>, ValueTask<bool>lub dowolny inny oczekiwany typ, którego metoda awaiter GetResult zwraca bool 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 Velement . 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:

Zobacz też