Partilhar via


Instruções de iteração - for, foreach, do, e while

As instruções de iteração executam repetidamente uma instrução ou um bloco de instruções. A for instrução executa seu corpo enquanto uma expressão booleana especificada é avaliada como true. A foreach instrução enumera os elementos de uma coleção e executa seu corpo para cada elemento da coleção. A do instrução executa condicionalmente seu corpo uma ou mais vezes. A while instrução executa condicionalmente seu corpo zero ou mais vezes.

Em qualquer ponto dentro do corpo de uma instrução de iteração, você pode sair do loop usando a break instrução. Você pode passar para a próxima iteração no loop usando a continue instrução.

Declaração for

A for instrução executa uma instrução ou um bloco de instruções, enquanto uma expressão booleana especificada é avaliada como true. O exemplo a seguir mostra a for instrução que executa seu corpo enquanto um contador inteiro é menor que três:

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

O exemplo anterior mostra os elementos for da instrução:

  • A seção do inicializador que é executada apenas uma vez, antes de entrar no loop. Normalmente, você declara e inicializa uma variável de loop local nessa seção. A variável declarada não pode ser acessada de fora da for instrução.

    A seção inicializador no exemplo anterior declara e inicializa uma variável de contador inteiro:

    int i = 0
    
  • A seção de condição que determina se a próxima iteração no loop deve ser executada. Se ele for avaliado como true ou não estiver presente, a próxima iteração será executada; caso contrário, o loop será encerrado. A seção de condição deve ser uma expressão booleana.

    A seção de condição no exemplo anterior verifica se um valor de contador é menor que três:

    i < 3
    
  • A seção iterador que define o que acontece após cada execução do corpo do loop.

    A seção iterador no exemplo anterior incrementa o contador:

    i++
    
  • O corpo do loop, que deve ser uma instrução ou um bloco de instruções.

A seção iterador pode conter zero ou mais das seguintes expressões de declaração, separadas por vírgulas.

Se você não declarar uma variável de loop na seção inicializador, poderá usar zero ou mais expressões da lista anterior na seção inicializador também. O exemplo a seguir mostra vários usos menos comuns das seções inicializador e iterador: atribuir um valor a uma variável externa na seção inicializador, invocar um método nas seções inicializador e iterador e alterar os valores de duas variáveis na seção iterador:

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

Todas as secções da for declaração são opcionais. Por exemplo, o código a seguir define o loop infinito for :

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

Declaração foreach

A foreach instrução executa uma instrução ou um bloco de instruções para cada elemento em uma instância de um tipo que implementa a interface System.Collections.IEnumerable ou a interface System.Collections.Generic.IEnumerable<T>, como mostra o exemplo a seguir.

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

A foreach declaração não se limita a esses tipos. Você pode usá-lo com uma instância de qualquer tipo que satisfaça as seguintes condições:

  • Um tipo tem o método público sem parâmetros GetEnumerator. O GetEnumerator método pode ser o método de extensão de um tipo.
  • O tipo de retorno do método GetEnumerator tem a propriedade pública Current e o método público sem parâmetros MoveNext cujo tipo de retorno é bool.

O exemplo a seguir usa a foreach instrução com uma instância do System.Span<T> tipo, que não implementa nenhuma interface:

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

Se a propriedade do Current enumerador devolver um valor de retorno de referência (ref T onde T representa o tipo de um elemento da coleção), pode declarar uma variável de iteração com os modificadores ref ou ref readonly, conforme demonstra o exemplo a seguir:

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

Se a coleção de origem da foreach instrução estiver vazia, o corpo da foreach instrução não será executado e ignorado. Se a foreach instrução for aplicada a null, a NullReferenceException é lançada.

aguardar por cada um

Você pode usar a await foreach instrução para consumir um fluxo assíncrono de dados, ou seja, o tipo de coleção que implementa a IAsyncEnumerable<T> interface. Cada iteração do loop pode ser suspensa enquanto o próximo elemento é recuperado de forma assíncrona. O exemplo a seguir mostra como usar a await foreach instrução:

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

Você também pode usar o await foreach comando com uma instância de qualquer tipo que satisfaça as seguintes condições:

  • Um tipo tem o método público sem parâmetros GetAsyncEnumerator. Esse método pode ser o método de extensão de um tipo.
  • O tipo de retorno do método GetAsyncEnumerator tem a propriedade pública Current e o método público sem parâmetros MoveNextAsync, cujo tipo de retorno é Task<bool>, ValueTask<bool> ou qualquer outro tipo aguardável cujo método do awaiter GetResult retorna um valor bool.

Por padrão, os elementos de fluxo são processados no contexto capturado. Se você quiser desativar a captura do contexto, use o TaskAsyncEnumerableExtensions.ConfigureAwait método de extensão. Para obter mais informações sobre contextos de sincronização e captura do contexto atual, consulte Consumindo o padrão assíncrono baseado em tarefas. Para obter mais informações sobre fluxos assíncronos, consulte o tutorial Fluxos assíncronos.

Tipo de uma variável de iteração

Você pode usar a var palavra-chave para permitir que o compilador infera o tipo de uma variável de iteração na foreach instrução, como mostra o código a seguir:

foreach (var item in collection) { }

Observação

O tipo de var pode ser inferido pelo compilador como um tipo de referência anulável, dependendo se o contexto consciente de nulidade está habilitado e se o tipo de uma expressão de inicialização é um tipo de referência. Para obter mais informações, consulte Variáveis locais digitadas implicitamente.

Você também pode especificar explicitamente o tipo de uma variável de iteração, como mostra o código a seguir:

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

Na forma anterior, o tipo T de um elemento de coleção deve ser implícita ou explicitamente convertível em tipo V de uma variável de iteração. Se uma conversão explícita de T para V falhar em tempo de execução, a instrução foreach lançará uma InvalidCastException. Por exemplo, se T for um tipo de classe não lacrada, V pode ser qualquer tipo de interface, mesmo aquela que T não implementa. Em tempo de execução, o tipo de um elemento de coleção pode ser aquele que deriva de T e realmente implementa V. Se não for esse o caso, um InvalidCastException é gerado.

Declaração do

A do instrução executa uma instrução ou um bloco de instruções, enquanto uma expressão booleana especificada é avaliada como true. Como essa expressão é avaliada após cada execução do loop, um do loop é executado uma ou mais vezes. O do loop difere do while loop, que executa zero ou mais vezes.

O exemplo a seguir mostra o uso da do instrução:

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

Declaração while

A while instrução executa uma instrução ou um bloco de instruções, enquanto uma expressão booleana especificada é avaliada como true. Como essa expressão é avaliada antes de cada execução do loop, um while loop é executado zero ou mais vezes. O while loop difere do do loop, que é executado uma ou mais vezes.

O exemplo a seguir mostra o uso da while instrução:

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

Especificação da linguagem C#

Para obter mais informações, consulte as seguintes seções da especificação da linguagem C#:

Para obter mais informações sobre esses recursos, consulte as seguintes notas de proposta de recurso:

Ver também