Iteratie-instructies - for, foreach, en dowhile

De iteratie-instructies voeren herhaaldelijk een instructie of een blok instructies uit. De for instructie voert de hoofdtekst uit terwijl een opgegeven Boole-expressie resulteert in true. Met foreach de instructie worden de elementen van een verzameling opgesomd en wordt de hoofdtekst voor elk element van de verzameling uitgevoerd. De do instructie voert de hoofdtekst een of meer keren voorwaardelijk uit. De while instructie voert voorwaardelijk de hoofdtekst nul of meer keren uit.

Op elk punt in de hoofdtekst van een iteratie-instructie kunt u de lus verbreken met behulp van de break instructie. U kunt stap voor stap naar de volgende iteratie in de lus gaan met behulp van de continue instructie.

De for instructie

Met de for instructie wordt een instructie of een blok instructies uitgevoerd terwijl een opgegeven Boole-expressie resulteert in true. In het volgende voorbeeld ziet u de instructie waarmee de for hoofdtekst wordt uitgevoerd, terwijl een teller voor gehele getallen kleiner is dan drie:

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

In het voorgaande voorbeeld ziet u de elementen van de for instructie:

  • De initialisatiesectie die slechts eenmaal wordt uitgevoerd, voordat u de lus invoert. Normaal gesproken declareert en initialiseert u een lokale lusvariabele in die sectie. De gedeclareerde variabele kan niet worden geopend van buiten de for instructie.

    De initialisatiesectie in het vorige voorbeeld declareert en initialiseert een tellervariabele voor gehele getallen:

    int i = 0
    
  • De voorwaardesectie die bepaalt of de volgende iteratie in de lus moet worden uitgevoerd. Als deze evalueert true of niet aanwezig is, wordt de volgende iteratie uitgevoerd. Anders wordt de lus afgesloten. De voorwaardesectie moet een Boole-expressie zijn.

    In de sectie Voorwaarde in het voorgaande voorbeeld wordt gecontroleerd of een tellerwaarde kleiner is dan drie:

    i < 3
    
  • De iteratorsectie die definieert wat er gebeurt na elke uitvoering van de hoofdtekst van de lus.

    In de iteratorsectie in het vorige voorbeeld wordt de teller verhoogd:

    i++
    
  • De hoofdtekst van de lus, die een instructie of een blok instructies moet zijn.

De iteratorsectie kan nul of meer van de volgende instructieexpressies bevatten, gescheiden door komma's:

Als u geen lusvariabele declareert in de sectie Initializer, kunt u ook nul of meer expressies uit de voorgaande lijst in de sectie Initializer gebruiken. In het volgende voorbeeld ziet u verschillende minder gangbare gebruikswijzen van de initialisatie- en iteratorsecties: het toewijzen van een waarde aan een externe variabele in de initialisatiesectie, het aanroepen van een methode in zowel de initialisatiefunctie als de iterator-secties, en het wijzigen van de waarden van twee variabelen in de iteratorsectie:

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 secties van de for instructie zijn optioneel. Met de volgende code wordt bijvoorbeeld de oneindige for lus gedefinieerd:

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

De foreach instructie

Met foreach de instructie wordt een instructie of een blok instructies uitgevoerd voor elk element in een exemplaar van het type dat de System.Collections.IEnumerable of System.Collections.Generic.IEnumerable<T> interface implementeert, zoals in het volgende voorbeeld wordt weergegeven:

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

De foreach instructie is niet beperkt tot deze typen. U kunt het gebruiken met een exemplaar van elk type dat voldoet aan de volgende voorwaarden:

  • Een type heeft de openbare methode zonder parameters GetEnumerator . De GetEnumerator methode kan de extensiemethode van een type zijn.
  • Het retourtype van de GetEnumerator methode heeft de openbare Current eigenschap en de openbare parameterloze MoveNext methode waarvan het retourtype is bool.

In het volgende voorbeeld wordt de foreach instructie gebruikt met een exemplaar van het System.Span<T> type, waarmee geen interfaces worden geïmplementeerd:

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

Als de eigenschap van Current de enumerator een retourwaarde retourneert (ref T waar T is het type verzamelingselement), kunt u een iteratievariabele declareren met de ref of ref readonly modifier, zoals in het volgende voorbeeld wordt weergegeven:

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

Als de bronverzameling van de foreach instructie leeg is, wordt de hoofdtekst van de foreach instructie niet uitgevoerd en overgeslagen. Als de foreach instructie wordt toegepast op null, wordt er een NullReferenceException gegenereerd.

wachten op foreach

U kunt de await foreach instructie gebruiken om een asynchrone gegevensstroom te gebruiken, dat wil zeggen het verzamelingstype waarmee de IAsyncEnumerable<T> interface wordt geïmplementeerd. Elke iteratie van de lus kan worden onderbroken terwijl het volgende element asynchroon wordt opgehaald. In het volgende voorbeeld ziet u hoe u de await foreach instructie gebruikt:

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

U kunt de await foreach instructie ook gebruiken met een exemplaar van elk type dat voldoet aan de volgende voorwaarden:

  • Een type heeft de openbare methode zonder parameters GetAsyncEnumerator . Deze methode kan de extensiemethode van een type zijn.
  • Het retourtype van de GetAsyncEnumerator methode heeft de openbare Current eigenschap en de openbare parameterloze MoveNextAsync methode waarvan het retourtype is Task<bool>, ValueTask<bool>of een ander te wachtend type waarvan de methode van GetResult de wachter een bool waarde retourneert.

Stream-elementen worden standaard verwerkt in de vastgelegde context. Als u het vastleggen van de context wilt uitschakelen, gebruikt u de TaskAsyncEnumerableExtensions.ConfigureAwait extensiemethode. Zie Het gebruik van het asynchrone patroon op basis van taken voor meer informatie over synchronisatiecontexten en het vastleggen van de huidige context. Zie de zelfstudie Asynchrone streams voor meer informatie over asynchrone streams.

Type iteratievariabele

U kunt het var trefwoord gebruiken om het type iteratievariabele in de foreach instructie te laten afleiden door de compiler, zoals in de volgende code wordt weergegeven:

foreach (var item in collection) { }

Notitie

var Het type kan worden afgeleid door de compiler als een null-referentietype, afhankelijk van of de context nullable is ingeschakeld en of het type initialisatie-expressie een verwijzingstype is. Zie Impliciet getypte lokale variabelen voor meer informatie.

U kunt ook expliciet het type iteratievariabele opgeven, zoals in de volgende code wordt weergegeven:

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

In het voorgaande formulier moet het type T verzamelingselement impliciet of expliciet worden omgezet in het type V iteratievariabele. Als een expliciete conversie van T naar V runtime mislukt, genereert de foreach instructie een InvalidCastException. Als dit bijvoorbeeld T een niet-verzegeld klassetype is, V kan elk interfacetype zijn, zelfs het type dat T niet wordt geïmplementeerd. Tijdens runtime kan het type verzamelingselement het element zijn dat is afgeleid van T en daadwerkelijk implementeert V. Als dat niet het geval is, wordt er een InvalidCastException gegooid.

De do instructie

Met de do instructie wordt een instructie of een blok instructies uitgevoerd terwijl een opgegeven Boole-expressie resulteert in true. Omdat deze expressie wordt geëvalueerd na elke uitvoering van de lus, wordt een of meer keren uitgevoerd do . De do lus verschilt van de while lus, die nul of meer keer wordt uitgevoerd.

In het volgende voorbeeld ziet u het gebruik van de do instructie:

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

De while instructie

Met de while instructie wordt een instructie of een blok instructies uitgevoerd terwijl een opgegeven Boole-expressie resulteert in true. Omdat deze expressie wordt geëvalueerd voordat elke uitvoering van de lus wordt uitgevoerd, wordt een while lus nul of meer keren uitgevoerd. De while lus verschilt van de do lus, die een of meer keren wordt uitgevoerd.

In het volgende voorbeeld ziet u het gebruik van de while instructie:

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

C#-taalspecificatie

Zie de volgende secties van de C#-taalspecificatie voor meer informatie:

Zie de volgende opmerkingen over functievoorstel voor meer informatie over deze functies:

Zie ook