C# else if
Com if e else, o programa escolhe entre dois caminhos. Mas muitas decisões têm mais de dois: a nota vira conceito A, B, C ou D; a compra ganha 15%, 10%, 5% ou nenhum desconto; a temperatura é "frio", "agradável" ou "calor". Para isso existe o else if ("senão, se"): uma cadeia de perguntas, feitas uma de cada vez, em que só o primeiro caminho verdadeiro roda.
- Como montar uma cadeia
if…else if…else. - Por que só o primeiro caminho verdadeiro roda, e por que a ordem das condições importa.
- Quando o
elsefinal é necessário (e o erroCS0165sem ele). - A diferença entre
else ife váriosifseparados. - Os erros de quem escreve
elseifouelif, ou põe oelseno lugar errado.
Todos os programas desta aula rodaram com o .NET 10 (C# 14) na máquina fictícia da Ana, na pasta ~/cs, com dotnet run arquivo.cs.
A ideia: a fila de perguntas
Pense no porteiro de um parque de diversões que confere a altura das crianças, com uma lista de perguntas na mão:
- "Tem 1,40 m ou mais?" Se sim: "pode ir na montanha-russa". Acabou, ele não lê o resto.
- Se não: "tem 1,20 m ou mais?" Se sim: "pode ir no carrinho de bate-bate". Acabou.
- Se não: "tem 1,00 m ou mais?" Se sim: "pode ir no carrossel". Acabou.
- Se nenhuma deu certo: "só o parquinho, por enquanto".
Duas coisas importam aqui: ele para na primeira resposta "sim", e a lista está na ordem certa, da exigência maior para a menor. Uma cadeia de else if funciona exatamente assim.
1. A primeira cadeia
A escola da Ana transforma a nota (de 0 a 10) num conceito: 9 ou mais é A, 7 ou mais é B, 5 ou mais é C, e abaixo disso é D.
double nota = 7.5;
if (nota >= 9)
{
Console.WriteLine($"Nota {nota}: conceito A");
}
else if (nota >= 7)
{
Console.WriteLine($"Nota {nota}: conceito B");
}
else if (nota >= 5)
{
Console.WriteLine($"Nota {nota}: conceito C");
}
else
{
Console.WriteLine($"Nota {nota}: conceito D");
}
Console.WriteLine("Boletim gerado.");
$ dotnet run conceito.cs Nota 7,5: conceito B « 7,5 >= 9? não. 7,5 >= 7? sim: para aqui Boletim gerado.
- if (nota >= 9)
- A primeira pergunta. Se for
true, roda o bloco do A e pula todo o resto da cadeia. - else if (nota >= 7)
- "Senão, se…": só é perguntado quando a anterior deu
false. Por isso não precisa escrevernota < 9 && nota >= 7: se o programa chegou aqui, a nota já é menor que 9. - else if (nota >= 5)
- Mais uma pergunta. Você pode pôr quantos
else ifquiser. - else
- O último caminho, sem condição: roda quando todas as perguntas deram
false. É opcional (seção 3). - Boletim gerado.
- Depois da cadeia, o programa continua normalmente, seja qual for o caminho que rodou.
O 7,5 com vírgula na saída é a cultura brasileira da máquina da Ana: no código, o número se escreve com ponto (7.5); ao mostrar, o .NET usa a vírgula (aula float, double e decimal).
Como o programa caminha, para algumas notas:
| Nota | >= 9? | >= 7? | >= 5? | Resultado |
|---|---|---|---|---|
| 9,5 | sim | (não pergunta) | (não pergunta) | A |
| 7,5 | não | sim | (não pergunta) | B |
| 5 | não | não | sim | C |
| 3 | não | não | não | D (o else) |
Missão: o programa diz "Calor" a partir de 30 graus e "Frio" até 15 graus, mas para 22 graus ele mostra "Frio", errado. Transforme o else num else if (temperatura <= 15) e acrescente um else final que mostre Agradável.
Agradável
int temperatura = 22;
if (temperatura >= 30)
{
Console.WriteLine("Calor");
}
else
{
Console.WriteLine("Frio");
}
int temperatura = 22;
if (temperatura >= 30)
{
Console.WriteLine("Calor");
}
else if (temperatura <= 15)
{
Console.WriteLine("Frio");
}
else
{
Console.WriteLine("Agradável");
}
Depois de passar, troque o 22 por 35, por 10, por 30 e por 15. Os limites (30 e 15) caem em "Calor" e "Frio", por causa do >= e do <=.
2. A ordem importa
Como a cadeia para na primeira condição verdadeira, a ordem das perguntas muda o resultado. Veja o que acontece se a Ana escrever as faixas de baixo para cima:
double nota = 9.5;
if (nota >= 5)
{
Console.WriteLine("Conceito C");
}
else if (nota >= 7)
{
Console.WriteLine("Conceito B");
}
else if (nota >= 9)
{
Console.WriteLine("Conceito A");
}
else
{
Console.WriteLine("Conceito D");
}
$ dotnet run ordem.cs Conceito C « a melhor nota da turma ganhou C!
9,5 é maior ou igual a 5, então a primeira pergunta já deu true, e o programa nem chegou às outras. Com essa ordem, nenhuma nota a partir de 5 consegue B ou A: esses dois blocos ficaram impossíveis de alcançar. E o compilador não avisa nada, porque ele não sabe o que você queria.
Com >=, comece pelo maior limite e desça (9, 7, 5). Com < ou <=, comece pelo menor e suba (< 5, < 7, < 9). Se as faixas estiverem certas, cada pergunta "corta" um pedaço, e o que sobra vai para a próxima.
3. O else final é opcional
Sem o else no fim, pode acontecer de nenhum caminho rodar:
int temperatura = 22;
if (temperatura >= 30)
{
Console.WriteLine("Calor");
}
else if (temperatura <= 15)
{
Console.WriteLine("Frio");
}
Console.WriteLine("Fim da previsão.");
$ dotnet run semelse.cs Fim da previsão. « 22 não é calor nem frio: nenhum bloco rodou
Às vezes é isso mesmo que você quer (só avisar nos extremos). Mas quando a cadeia precisa sempre produzir um resultado, o else é obrigatório. O compilador sabe disso, e reclama quando uma variável pode ficar sem valor:
int nota = 8;
string conceito;
if (nota >= 9)
{
conceito = "A";
}
else if (nota >= 7)
{
conceito = "B";
}
Console.WriteLine($"Conceito {conceito}");
$ dotnet run semvalor.cs /home/ana/cs/semvalor.cs(11,31): error CS0165: Uso de variável local não atribuída "conceito" Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
Se a nota fosse 4, nenhuma das duas perguntas daria true e conceito ficaria sem valor. O compilador olha todos os caminhos, não só a nota 8 de agora. Acrescente else { conceito = "C ou D"; } e o erro some: agora todo caminho dá um valor.
4. else if não é uma palavra nova
Uma curiosidade que ajuda a entender: o C# não tem uma instrução else if. É só um else cujo bloco é outro if. A cadeia da seção 1 é exatamente este programa, escrito com ifs "um dentro do outro":
double nota = 7.5;
if (nota >= 9)
{
Console.WriteLine("Conceito A");
}
else
{
if (nota >= 7)
{
Console.WriteLine("Conceito B");
}
else
{
if (nota >= 5)
{
Console.WriteLine("Conceito C");
}
else
{
Console.WriteLine("Conceito D");
}
}
}
$ dotnet run aninhado.cs Conceito B
Mesmo resultado, mas o código vai "entortando" para a direita a cada faixa. Escrever else if numa linha só é a forma de manter a cadeia reta e fácil de ler. É por isso que a regra "chaves sempre" da aula anterior tem uma única exceção aceita por todo mundo: entre o else e o if, não vão chaves.
5. Faixas com &&
Às vezes fica mais claro escrever a faixa inteira, com && ("e"). O cinema da Ana cobra meia-entrada de crianças com menos de 12 anos e de quem tem 60 ou mais:
int idade = 35;
if (idade < 12)
{
Console.WriteLine("Criança: meia-entrada");
}
else if (idade >= 12 && idade < 60)
{
Console.WriteLine("Inteira");
}
else
{
Console.WriteLine("60+: meia-entrada");
}
$ dotnet run faixa.cs Inteira
O idade >= 12 é redundante: se o programa chegou ao else if, a idade já não é menor que 12. Funciona igual com ou sem ele. Algumas pessoas preferem escrever a faixa completa porque ela se explica sozinha; outras preferem a forma curta. As duas estão certas.
6. else if ou vários if?
Parece a mesma coisa escrever três if separados, mas não é. Cada if separado é uma pergunta nova, feita sempre, e mais de um bloco pode rodar:
double nota = 9.5;
if (nota >= 9)
{
Console.WriteLine("Conceito A");
}
if (nota >= 7)
{
Console.WriteLine("Conceito B");
}
if (nota >= 5)
{
Console.WriteLine("Conceito C");
}
$ dotnet run separados.cs Conceito A « 9,5 >= 9 Conceito B « 9,5 >= 7 também Conceito C « e 9,5 >= 5 também: três conceitos para uma nota!
Cadeia if / else if | Vários if separados | |
|---|---|---|
| Quantos blocos rodam | No máximo um (exatamente um, se tiver else) | Zero, um ou vários |
| Quando usar | As opções se excluem: um conceito, uma faixa de desconto | As perguntas são independentes: "tem ovos?", "tem leite?", "tem pão?" (cada resposta gera um aviso) |
Formas diferentes + qual usar
| Situação | Use |
|---|---|
| Dois caminhos | if / else (if e else) |
Três ou mais caminhos com faixas (>=, <) ou condições diferentes | if / else if / else (esta aula) |
| Vários caminhos que comparam a mesma variável com valores exatos (1, 2, 3; "pix", "cartão") | switch |
| Escolher um valor por faixas, numa expressão | Expressões switch (nota switch { >= 9 => "A", … }) |
Quando dá errado
elseif ou elif: error CS1002: ; esperado
$ cat elseif.cs
int nota = 8;
if (nota >= 9)
{
Console.WriteLine("A");
}
elseif (nota >= 7)
{
Console.WriteLine("B");
}
$ dotnet run elseif.cs
/home/ana/cs/elseif.cs(6,19): error CS1002: ; esperado
Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
O que significa: em C#, são duas palavras: else if. Grudadas, elseif vira um nome qualquer, e elseif (nota >= 7) parece a chamada de um método chamado elseif. Uma chamada termina com ;, e o compilador reclama que o ; faltou no fim da linha 6 (coluna 19). Com o elif do Python, a mesma coisa: elif.cs(6,17): error CS1002: ; esperado.
O compilador para nesse erro de sintaxe e nem chega a procurar o outro problema (o nome elseif não existe). O editor do guia faz igual e mostra só o mesmo CS1002.
Como consertar: else if (nota >= 7), com espaço. (Também existe #elif em C#, mas é outra coisa: uma diretiva do pré-processador, que você não vai usar agora.)
error CS8641: 'else' não pode iniciar uma instrução.
$ cat elseantes.cs
int nota = 8;
if (nota >= 9)
{
Console.WriteLine("A");
}
else
{
Console.WriteLine("C");
}
else if (nota >= 7)
{
Console.WriteLine("B");
}
$ dotnet run elseantes.cs
/home/ana/cs/elseantes.cs(9,2): error CS8641: 'else' não pode iniciar uma instrução.
/home/ana/cs/elseantes.cs(9,2): error CS1003: Erro de sintaxe, "(" esperado
/home/ana/cs/elseantes.cs(9,2): error CS1525: Termo de expressão inválido "else"
/home/ana/cs/elseantes.cs(9,2): error CS1026: ) esperado
/home/ana/cs/elseantes.cs(9,2): error CS1002: ; esperado
Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
O que significa: o else sem condição fecha a cadeia. Depois dele, a cadeia acabou, e o else if seguinte ficou sem if para se pendurar. Os quatro erros depois do primeiro são consequência dele.
Como consertar: o else sozinho vai sempre por último. Mova o else if para antes dele.
error CS0165: Uso de variável local não atribuída depois de uma cadeia
O que significa: a cadeia não tem else, então existe um caminho em que a variável não recebe valor.
Como consertar: acrescente o else final dando um valor, ou dê um valor inicial na declaração.
O que significa: quase sempre, a ordem das condições (seção 2) ou um > no lugar de >= nos limites. O compilador não tem como saber.
Como consertar: teste o programa com os valores dos limites (9, 7, 5) e com um valor de cada faixa. Se as faixas usam >=, confira se elas estão do maior para o menor.
Referência rápida
| Estrutura | O que faz |
|---|---|
if (c1) { A } else if (c2) { B } else { C } | Roda A se c1; senão, B se c2; senão, C. Exatamente um dos três. |
if (c1) { A } else if (c2) { B } | Sem else: pode não rodar nenhum. |
Ordem das faixas com >= | Do maior limite para o menor. |
Ordem das faixas com < | Do menor limite para o maior. |
else sozinho | Sempre o último da cadeia. |
elseif, elif | Não existem em C# (CS1002). Escreva else if. |
Exercícios
1. Senão, se
Complete com as duas palavras que continuam a cadeia:
2. O que aparece?
Com int pontos = 70;, o que este código mostra?
if (pontos >= 90) { Console.WriteLine("Ouro"); }
else if (pontos >= 60) { Console.WriteLine("Prata"); }
else if (pontos >= 30) { Console.WriteLine("Bronze"); }
else { Console.WriteLine("Sem medalha"); }
3. O último da cadeia
Qual palavra, sozinha e sem condição, fecha uma cadeia de else if?
4. Com int idade = 70;, o que mostra if (idade >= 18) { Console.WriteLine("Adulto"); } else if (idade >= 60) { Console.WriteLine("Idoso"); }?
5. Qual é a diferença entre uma cadeia if/else if e vários if separados?
6. O que o compilador responde a elif (x > 0)?
Missão final: o desconto progressivo
Missão: a lojinha da Ana dá desconto pelo valor da compra: 15% a partir de R$ 500, 10% a partir de R$ 200, 5% a partir de R$ 100 e nenhum desconto abaixo disso. Monte a cadeia de if / else if / else que dá o valor certo a desconto. (Repare que int desconto; está sem valor: se faltar o else, você vai ver o CS0165.) Com a compra de 250, a saída deve ser:
Desconto: 10% Total: R$ 225,00
decimal compra = 250m;
int desconto;
// escreva a cadeia aqui
decimal total = compra - compra * desconto / 100;
Console.WriteLine($"Desconto: {desconto}%");
Console.WriteLine($"Total: R$ {total:N2}");
decimal compra = 250m;
int desconto;
if (compra >= 500m)
{
desconto = 15;
}
else if (compra >= 200m)
{
desconto = 10;
}
else if (compra >= 100m)
{
desconto = 5;
}
else
{
desconto = 0;
}
decimal total = compra - compra * desconto / 100;
Console.WriteLine($"Desconto: {desconto}%");
Console.WriteLine($"Total: R$ {total:N2}");
Teste com os limites: 500 (15%), 499,99 (10%), 200 (10%), 100 (5%) e 99,90 (0%). Se algum der errado, confira a ordem da cadeia.
Resumo
if…else if…elseescolhe entre vários caminhos. As perguntas são feitas em ordem, e só o primeiro caminho verdadeiro roda.- A ordem importa: com
>=, do maior limite para o menor. O compilador não avisa quando a ordem está errada. - O
elsefinal é opcional e vai sempre por último. Sem ele, pode não rodar nada, e uma variável pode ficar sem valor (CS0165). else ifé umelsecujo bloco é outroif; são duas palavras.elseifeelifnão existem (CS1002).- Use a cadeia quando as opções se excluem; use
ifs separados quando as perguntas são independentes.