break encerra um laço antes do fim. continue pula o resto da iteração atual e passa para a próxima. Os dois valem para o laço mais interno que os contém, e funcionam do mesmo jeito em for, foreach, while e do while.
Saída:
process order of 45
skip invalid total 0
process order of 120
skip invalid total -5
process order of 80
test order found, stopping
after the loop
continue pulou a linha de processamento para 0 e -5. break parou o laço em 999, então 60 nunca foi visitado, e a execução seguiu na primeira instrução depois do laço.
break: pare quando a resposta for conhecida
O uso típico de break é uma busca: depois de encontrar o que você procurava, não há motivo para olhar o resto.
Saída:
first invalid email at index 1
O iterador (i++) não executa depois de um break, então i ainda guardaria o índice encontrado se tivesse sido declarado fora do laço. Para buscas simples, uma chamada de biblioteca diz a mesma coisa: Array.FindIndex(emails, e => !e.Contains("@")) retorna o índice (ou -1), e o emails.Any(e => !e.Contains("@")) do LINQ responde se existe algum inválido.
continue: pule para a próxima iteração
continue é uma guard clause para laços. Em vez de envolver o trabalho real em um if, rejeite logo no início os casos que você não quer:
Saída:
pen costs 1.20
mug costs 8.00
Para onde o continue vai depende do laço. Em um laço for, ele executa o iterador e depois testa a condição. Em um laço while, ele pula direto para a condição, o que leva a um bug clássico:
int i = 0;
while (i < 10)
{
if (i % 2 == 0)
continue; // i++ below is skipped: i stays 0 forever
Console.WriteLine(i);
i++;
}
Atualize o contador antes de qualquer continue, ou use um laço for, em que a atualização fica no cabeçalho e sempre executa.
break dentro de um switch dentro de um laço
Em um switch, break encerra a seção do case. Quando esse switch está em um laço, o break pertence ao switch, não ao laço:
Saída:
quit received
count = 2
Um break simples no case "quit" teria encerrado só o switch, o laço teria continuado e count seria 3. O goto pula para o rótulo depois do laço. Mover o laço para um método e escrever return nesse case também funciona e dispensa o rótulo.
Saindo de laços aninhados
C# não tem break com rótulo como o break outer; do Java. Quando uma busca passa por dois laços aninhados, um break no laço interno só encerra o interno; o laço externo passa para a próxima linha. Há três soluções padrão.
1. Uma flag que o laço externo verifica:
Saída:
first free seat: row 1, seat 2
2. goto para um rótulo depois dos dois laços. É o único lugar em que muitos guias de estilo de C# aceitam goto, porque ele expressa exatamente "sair dos dois laços":
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < cols; col++)
{
if (seats[row, col] == 0)
{
Console.WriteLine($"first free seat: row {row}, seat {col}");
goto done;
}
}
}
done:
Console.WriteLine("search finished");
3. Um método com return, normalmente o mais limpo, porque a busca ganha um nome e pode retornar o resultado:
Saída:
first free seat: row 1, seat 2
O C# 7.0 também introduziu as funções locais, que permitem colocar esse método auxiliar dentro do método que o chama. O padrão com parâmetro out usado aqui é explicado na página de ref e out.
goto e rótulos
Um rótulo é um identificador seguido de dois pontos, e goto label; pula para ele. As regras são rígidas o bastante para evitar o pior uso:
- O rótulo precisa estar no mesmo método, no mesmo bloco do
gotoou em um bloco que o contém. Você pode pular para fora de blocos, mas nunca para dentro de um: pular de fora para um rótulo dentro do corpo de um laço é o erro CS0159 (não existe esse rótulo no escopo da instrução goto). - Você não pode sair de um bloco
finallycomgoto,breakoucontinue. - Dentro de um
switch,goto case 3;egoto default;transferem o controle para outra seção. É assim que um switch em C# expressa o fall through, já que cair no próximo case de forma implícita é um erro de compilação.
goto também pode construir laços (pulando para trás até um rótulo), mas um laço while diz a mesma coisa em uma forma que qualquer leitor reconhece. Deixe o goto para sair de laços aninhados e para seções de switch.
return, throw e laços
return sai do método inteiro, então também sai de todos os laços dentro dele. throw faz o mesmo lançando uma exceção. Dentro de um bloco try com finally, break, continue, goto e return ainda executam o bloco finally antes de o controle seguir, e é isso que torna seguro sair de um laço que mantém um arquivo aberto em um bloco using.
| Instrução | Sai de | Continua em |
|---|---|---|
continue | a iteração atual | a próxima iteração (iterador, depois condição) |
break | o laço ou switch mais interno | a instrução seguinte |
goto label | quaisquer blocos que o contêm | o rótulo |
return | o método | quem chamou |
throw | tudo até um catch correspondente | o bloco catch |
Perguntas frequentes
Qual a diferença entre break e continue em C#?
break encerra imediatamente o laço mais interno (ou o switch); a execução continua depois dele. continue encerra só a iteração atual e pula para a próxima: em um laço for o iterador executa em seguida, em while e do while a condição é testada em seguida, e no foreach o próximo elemento é buscado.
Como sair de laços aninhados em C#?
C# não tem break com rótulo. As três opções são: definir uma flag bool e testá-la no laço externo, pular para depois dos dois laços com goto até um rótulo, ou mover os laços para um método e usar return nele. A versão com método costuma ser a mais limpa, porque também dá um nome e um valor de retorno para a busca.
Um break dentro de um switch sai do laço em C#?
Não. Dentro de um switch que está em um laço, break encerra a seção do switch e o laço continua. Para sair do laço de dentro de um case, use return, uma flag verificada depois do switch, ou goto para um rótulo depois do laço. Já continue dentro de um case vai para a próxima iteração do laço.
goto é permitido em C#?
Sim. goto label; pula para label: no mesmo método, mas não pode pular para dentro de um bloco nem sair de um finally. Dentro de um switch, goto case value; e goto default; pulam entre seções. Fora sair de laços aninhados e o fall through explícito do switch, goto raramente é a escolha mais clara.