Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Sugestão
Este artigo faz parte da secção Fundamentos para programadores que já conhecem pelo menos uma linguagem de programação e estão a aprender C#. Se és novo na programação, começa primeiro pelos tutoriais para começar . Para a sintaxe completa, veja instruções de iteração na referência da linguagem.
Vem de outra língua? Todos os quatro ciclos C# (foreach, while,do-while , e for) têm equivalentes diretos em Java, C++ e JavaScript. Usas foreach mais vezes. Ele itera uma coleção sem um índice, como o enhanced for do Java ou o do JavaScript for...of.
As instruções de iteração executam repetidamente um bloco de código. Cada passagem pelo bloco é uma iteração, e um bloco que se repete é um ciclo. C# tem quatro ciclos. Comece por foreach para coleções, use while edo-whilequando uma condição controla a repetição, e use for quando precisar de um índice explícito.
Iterar uma coleção com foreach
A instrução foreach executa o respetivo corpo uma vez por cada elemento de uma coleção, pela ordem. É a escolha mais comum para ler uma coleção, porque não tens de gerir um índice nem fazer a verificação dos limites. A foreach instrução previne erros típicos de desligamento por um:
string[] names = ["Ana", "Ben", "Cleo"];
// foreach reads each element in order. It's the default loop for
// collections: no index to manage and no off-by-one mistakes.
foreach (string name in names)
{
Console.WriteLine(name); // => Ana, then Ben, then Cleo
}
foreach funciona com qualquer tipo que C# reconheça como uma sequência, incluindo arrays, List<T>, e Dictionary<TKey,TValue>. A variável de iteração (name no exemplo anterior) é só de leitura, por isso não podes reatribui-la dentro do ciclo.
O corpo de um ciclo é uma única afirmação, como uma atribuição ou uma chamada de método. Uma instrução de bloco é, por si só, uma única instrução que engloba zero ou mais instruções entre chavetas ({ }).
Muitos padrões de codificação recomendam que o corpo do ciclo seja delimitado por chavetas, mesmo que contenha apenas uma única instrução. As chavetas tornam o âmbito explícito. Evita um erro comum: adicionar posteriormente uma segunda linha que se espera que seja executada em cada iteração, mas que, em vez disso, é executada uma única vez após o ciclo. Só as chavetas decidem que instruções pertencem ao ciclo. O C# não trata o espaço em branco como algo significativo, por isso a indentação sozinha nunca o faz. As chaves são válidas mesmo com uma única linha: o bloco é a única instrução que o ciclo repete. Indente o código para facilitar a leitura, mas use as chavetas para definir o bloco.
Repete enquanto uma condição se mantém com while
Um while ciclo verifica a sua condição booleana antes de cada iteração. Se a condição for false no início, o corpo nunca é executado, por isso um ciclo while executa-se zero ou mais vezes:
int countdown = 3;
// A while loop checks its condition before each iteration, so the body
// runs zero or more times.
while (countdown > 0)
{
Console.WriteLine(countdown); // => 3, then 2, then 1
countdown--;
}
Certifica-te de que algo dentro do circuito altera a condição. No exemplo anterior, countdown-- acaba por tornar a condição false verdadeira. Um ciclo cuja condição nunca se torna false executa-se indefinidamente.
Passa pelo corpo pelo menos uma vez com do-while
Um do-while ciclo verifica a condição após cada iteração, por isso o corpo é sempre executado pelo menos uma vez. Utilize-o quando a primeira iteração tiver de ocorrer antes de poder avaliar a condição, como ao solicitar dados e depois validá-los:
int attempts = 0;
// A do-while loop runs its body once, then checks the condition. Use it
// when the body must run at least one time.
do
{
attempts++;
Console.WriteLine($"Attempt {attempts}"); // => Attempt 1, then Attempt 2, then Attempt 3
}
while (attempts < 3);
Contar com for
Uma for instrução loop contém três partes: um inicializador que corre uma vez antes do loop, uma condição verificada antes de cada iteração, e um iterador que corre após cada iteração. Usa for quando precisares do índice em si, não só dos elementos. Normalmente, precisas do índice quando queres modificar o elemento em vez de ler o seu valor.
// A for loop fits when you need an explicit index. The three parts are
// the initializer, the condition, and the iterator.
for (int i = 0; i < 3; i++)
{
Console.WriteLine(i); // => 0, then 1, then 2
}
Quando apenas lês os elementos, quando não usas as posições ou não atribuis novos valores, prefere foreach. Declara a intenção de forma mais clara e evita a aritmética indexada.
Sair ou saltar com break e continue
Duas instruções de salto permitem um controlo mais preciso dentro de qualquer ciclo. A break instrução sai imediatamente do ciclo, saltando quaisquer iterações restantes:
int[] numbers = [2, 4, 7, 8];
// break stops the loop immediately, skipping any remaining elements.
foreach (int number in numbers)
{
if (number % 2 != 0)
{
Console.WriteLine($"First odd number: {number}"); // => First odd number: 7
break;
}
}
A continue instrução salta o resto da iteração atual e passa para a seguinte:
int[] values = [1, 2, 3, 4, 5];
// continue skips the rest of the current iteration and moves to the next.
foreach (int value in values)
{
if (value % 2 == 0)
{
continue; // skip even numbers
}
Console.WriteLine(value); // => 1, then 3, then 5
}
Iterar um fluxo assíncrono com await foreach
Um fluxo assíncrono é um leitor que utiliza uma tarefa assíncrona para produzir cada elemento seguinte. C# representa isso com a IAsyncEnumerable<T> interface. Os dados que chegam ao longo do tempo, como páginas de uma API web ou linhas de uma base de dados, encaixam-se neste modelo: recuperar o próximo elemento é uma operação aguardável em vez de um retorno imediato.
Para consumir um fluxo assíncrono, coloque a palavra-chave await antes de foreach. Cada iteração aguarda o próximo elemento, por isso o loop suspende-se enquanto esse elemento é produzido em vez de bloquear o thread:
private static async Task AwaitForeachExample()
{
// await foreach consumes an asynchronous stream. Each iteration can
// suspend while the next element is produced.
await foreach (int value in GenerateAsync())
{
Console.WriteLine(value); // => 0, then 1, then 2
}
}
private static async IAsyncEnumerable<int> GenerateAsync()
{
for (int i = 0; i < 3; i++)
{
await Task.Delay(1); // stand-in for real asynchronous work
yield return i;
}
}
Os fluxos assíncronos baseiam-se em async e await. Para uma explicação completa, veja Gerar e consumir fluxos assíncronos.