Freigeben über


Iterationsanweisungen - for, foreach, , dound while

Die Iterationsanweisungen führen wiederholt eine Anweisung oder einen Block von Anweisungen aus. Die for Anweisung führt ihren Body aus, während ein angegebener boolescher Ausdruck zu true ausgewertet wird. Die foreach Anweisung listet die Elemente einer Collection auf und führt ihren Body für jedes Element der Collection aus. Die Anweisung do führt ihren Body ein oder mehrere Male bedingt aus. Die while Anweisung führt ihren Body bedingt null oder mehr Mal aus.

An jedem Punkt innerhalb des Textkörpers einer Iterationsanweisung können Sie die Schleife mithilfe der break Anweisung ausbrechen. Sie können die nächste Iteration in der Schleife mithilfe der continue Anweisung ausführen.

Die Anweisung for

Die Anweisung for führt eine Anweisung oder einen Anweisungsblock aus, während ein angegebener boolescher Ausdruck true ergibt. Das folgende Beispiel zeigt die Anweisung for, die ihren Rumpf ausführt, solange ein Zähler für eine ganze Zahl kleiner als drei ist:

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

Das vorangehende Beispiel zeigt die Elemente der for Anweisung.

  • Den Abschnitt initializer, der nur einmal ausgeführt wird, bevor die Schleife beginnt. In der Regel deklarieren und initialisieren Sie eine lokale Schleifenvariable in diesem Abschnitt. Auf die deklarierte Variable kann nicht von außerhalb der for Anweisung zugegriffen werden.

    Der Initialisierungsabschnitt im vorherigen Beispiel deklariert und initialisiert eine Ganzzahlzählervariable:

    int i = 0
    
  • Der Bedingungsabschnitt , der bestimmt, ob die nächste Iteration in der Schleife ausgeführt werden soll. Wenn die Auswertung true ergibt oder fehlt, wird die nächste Iteration ausgeführt, andernfalls wird die Schleife verlassen. Der Bedingungsabschnitt muss ein boolescher Ausdruck sein.

    Im Abschnitt "Bedingung " im vorherigen Beispiel wird überprüft, ob ein Zählerwert kleiner als drei ist:

    i < 3
    
  • Den Abschnitt iterator, der definiert, was nach jeder Iteration des Schleifenrumpfs geschieht.

    Der Abschnitt "Iterator " im vorherigen Beispiel erhöht den Zähler:

    i++
    
  • Den Schleifenrumpf, der entweder eine Anweisung oder ein Anweisungsblock sein muss.

Der Iteratorabschnitt kann null oder mehr der folgenden Anweisungsausdrücke enthalten, getrennt durch Kommas:

Wenn Sie keine Schleifenvariable im Initialisierungsabschnitt deklarieren, können Sie auch null oder mehr der Ausdrücke aus der vorherigen Liste im Initialisiererabschnitt verwenden. Das folgende Beispiel zeigt mehrere weniger häufige Verwendungen des Initialisierungs- und Iteratorabschnitts: Zuweisen eines Werts zu einer externen Variablen im Initialisierungsabschnitt, Aufrufen einer Methode in den Abschnitten "Initialisierer" und "Iterator" und Ändern der Werte von zwei Variablen im Iterator-Abschnitt:

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

Alle Abschnitte der for Anweisung sind optional. Der folgende Code definiert z. B. die Unendliche for Schleife:

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

Die Anweisung foreach

Die foreach-Anweisung führt eine Anweisung oder einen Block von Anweisungen für jedes Element in einer Instanz des Typs aus, der die System.Collections.IEnumerable- oder System.Collections.Generic.IEnumerable<T>-Schnittstelle implementiert, wie das folgende Beispiel zeigt.

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

Die foreach Anweisung ist nicht auf diese Typen beschränkt. Sie können es mit einer Instanz eines beliebigen Typs verwenden, der die folgenden Bedingungen erfüllt:

  • Ein Typ weist die öffentliche parameterlose GetEnumerator Methode auf. Die GetEnumerator Methode kann die Erweiterungsmethode eines Typs sein.
  • Der Rückgabetyp der GetEnumerator Methode weist die öffentliche Current Eigenschaft und die öffentliche parameterlose MoveNext Methode auf, deren Rückgabetyp lautet bool.

Im folgenden Beispiel wird die foreach Anweisung mit einer Instanz des System.Span<T> Typs verwendet, die keine Schnittstellen implementiert:

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

Wenn die Eigenschaft des Enumerators Current einen Rückgabewert eines Verweises zurückgibt (ref T dabei T handelt es sich um den Typ eines Auflistungselements), können Sie eine Iterationsvariable mit dem ref oder ref readonly Modifizierer deklarieren, wie das folgende Beispiel zeigt.

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

Wenn die Quellauflistung der foreach Anweisung leer ist, wird der Textkörper der foreach Anweisung nicht ausgeführt und übersprungen. Wenn die foreach-Anweisung auf null angewendet wird, wird NullReferenceException ausgelöst.

await foreach

Mit der await foreach Anweisung können Sie einen asynchronen Datenstrom verwenden, d. h. den Sammlungstyp, der die IAsyncEnumerable<T> Schnittstelle implementiert. Jede Iteration der Schleife kann angehalten werden, während das nächste Element asynchron abgerufen wird. Das folgende Beispiel zeigt die Verwendung der await foreach Anweisung:

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

Sie können die await foreach Anweisung auch mit einer Instanz eines beliebigen Typs verwenden, die die folgenden Bedingungen erfüllt:

  • Ein Typ weist die öffentliche parameterlose GetAsyncEnumerator Methode auf. Diese Methode kann die Erweiterungsmethode eines Typs sein.
  • Der Rückgabetyp der GetAsyncEnumerator-Methode hat die öffentliche Current-Eigenschaft und die öffentliche parameterlose MoveNextAsync-Methode, deren Rückgabetyp Task<bool>, ValueTask<bool> oder ein beliebiger anderer awaitable-Typ ist, dessen GetResult-Methode des „awaiter“-Elements einen bool-Wert zurückgibt.

Streamelemente werden standardmäßig im erfassten Kontext verarbeitet. Wenn Sie die Erfassung des Kontexts deaktivieren möchten, verwenden Sie die TaskAsyncEnumerableExtensions.ConfigureAwait Erweiterungsmethode. Weitere Informationen zu Synchronisierungskontexten und zum Erfassen des aktuellen Kontexts finden Sie unter Verwenden des aufgabenbasierten asynchronen Musters. Weitere Informationen zu asynchronen Datenströmen finden Sie im Lernprogramm "Asynchrone Datenströme".

Typ einer Iterationsvariable

Sie können das var Schlüsselwort verwenden, damit der Compiler den Typ einer Iterationsvariable in der foreach Anweisung ableiten kann, wie der folgende Code zeigt:

foreach (var item in collection) { }

Hinweis

Der Typ von var kann vom Compiler als nullfähiger Verweistyp abgeleitet werden, abhängig davon, ob der nullfähige Kontext aktiviert ist und ob der Typ eines Initialisierungsausdrucks ein Verweistyp ist. Weitere Informationen finden Sie unter implizit typierten lokalen Variablen.

Sie können auch explizit den Typ einer Iterationsvariable angeben, wie der folgende Code zeigt:

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

Im vorherigen Formular muss der Typ T eines Sammlungselements implizit oder explizit in den Typ V einer Iterationsvariablen konvertierbar sein. Wenn zur Laufzeit eine explizite Konvertierung von T nach V fehlschlägt, wirft die foreach-Anweisung eine InvalidCastException. Zum Beispiel, wenn T ein nicht versiegelter Klassentyp ist, kann V ein beliebiger Schnittstellentyp sein, selbst wenn T nicht implementiert wird. Zur Laufzeit kann der Typ eines Sammlungselements der Typ sein, der von T ableitet und wirklich V implementiert. Wenn dies nicht der Fall ist, wird eine InvalidCastException ausgelöst.

Die Anweisung do

Die Anweisung do führt eine Anweisung oder einen Anweisungsblock aus, während ein angegebener boolescher Ausdruck true ergibt. Da der Ausdruck nach jeder Ausführung der Schleife ausgewertet wird, wird eine do-Schleife mindestens einmal ausgeführt. Die do Schleife unterscheidet sich von der while Schleife, die null oder mehr mal ausgeführt wird.

Das folgende Beispiel zeigt die Verwendung der do Anweisung:

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

Die Anweisung while

Die Anweisung while führt eine Anweisung oder einen Anweisungsblock aus, während ein angegebener boolescher Ausdruck true ergibt. Da der Ausdruck vor jeder Ausführung der Schleife ausgewertet wird, wird eine while-Schleife entweder nie oder mehrmals ausgeführt. Die while Schleife unterscheidet sich von der do Schleife, die mindestens einmal ausgeführt wird.

Das folgende Beispiel zeigt die Verwendung der while Anweisung:

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

C#-Sprachspezifikation

Weitere Informationen finden Sie in den folgenden Abschnitten der C#-Sprachspezifikation:

Weitere Informationen zu diesen Features finden Sie in den folgenden Featurevorschlägen:

Siehe auch