Partilhar via


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

Use instruções de iteração para executar 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, pode sair do ciclo usando a break sentença. Pode avançar para a próxima iteração do ciclo usando a continue instrução.

A referência da linguagem C# documenta a versão mais recentemente lançada da linguagem C#. Contém também documentação inicial para funcionalidades em pré-visualizações públicas para o próximo lançamento linguístico.

A documentação identifica qualquer funcionalidade introduzida pela primeira vez nas últimas três versões da língua ou em pré-visualizações públicas atuais.

Sugestão

Para saber quando uma funcionalidade foi introduzida pela primeira vez em C#, consulte o artigo sobre o histórico de versões da linguagem C#.

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 secção inicializadora que é executada apenas uma vez, antes de entrar no ciclo. Normalmente, você declara e inicializa uma variável de loop local nessa seção. Não podes aceder à variável declarada a partir 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 secção de condição que determina se a próxima iteração no ciclo deve ser executada. Se avaliar ou true não estiver presente, a próxima iteração é executada. Caso contrário, o loop sai. 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 um método de extensão.
  • 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 foreach corpo da instrução não é executado nem ignorado. Se a foreach instrução for aplicada a null, a NullReferenceException é lançada.

aguardar por cada um

Use a await foreach instrução para consumir um fluxo assíncrono de dados, ou seja, um tipo de coleção que implementa a IAsyncEnumerable<T> interface. Cada iteração do ciclo pode suspender-se 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. Este método pode ser um membro de extensão.
  • 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 defeito, a await foreach instrução processa elementos do fluxo 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

Use a var palavra-chave para permitir que o compilador infira o tipo de variável de iteração na foreach instrução, como o seguinte código mostra:

foreach (var item in collection) { }

Observação

O compilador pode inferir o tipo de declaração var como um tipo de referência anulável, dependendo se o contexto consciente anulável está ativado e se o tipo de expressão de inicialização é um tipo de referência. Para mais informações, veja Variáveis locais implicitamente tipadas.

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 elemento de coleção pode ser aquele que deriva de T e implementa efetivamente 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 o ciclo avalia essa expressão após cada execução, um do ciclo executa-se 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 o ciclo avalia essa expressão antes de cada execução, um while ciclo executa 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#:

Ver também