If mais limpo em C#: ternário, retorno antecipado e pattern matching

Resumo rápido
- Este post é para quem já sabe usar if, else e else if e quer escrever condições mais fáceis de ler.
- Ternário (
? :) escolhe entre dois valores numa linha. - Retorno antecipado acaba com a escada de if dentro de if.
- Condições longas ficam melhores com um nome: uma variável
boolou um método. ise a expressãoswitchcom padrões testam faixas e tipos sem repetir a variável.??dá um valor padrão quando algo énull.
Se você ainda está aprendendo o básico, comece pelo post If, else e else if em C#. Aqui o assunto é outro: o seu if já funciona, mas está difícil de ler. Vamos ver cinco técnicas para deixar as decisões do jogo mais limpas.
O problema: a escada de if

Abrir a porta do laboratório exige estar vivo, ter o cartão e ter energia no prédio. Escrito de qualquer jeito, vira isto:
C#
Console.WriteLine(TentarAbrir(80, true, false));
static string TentarAbrir(int vida, bool temCartao, bool temEnergia)
{
if (vida > 0)
{
if (temCartao)
{
if (temEnergia)
{
return "Porta aberta.";
}
else
{
return "Sem energia no prédio.";
}
}
else
{
return "Você precisa do cartão.";
}
}
else
{
return "Você está morto.";
}
}
Saída esperada
Sem energia no prédio.
Funciona, mas para achar qual mensagem pertence a qual if você precisa contar chaves. Cada nova regra empurra o código mais para a direita.
1. Retorno antecipado

Inverta as condições e saia do método assim que algo der errado. O caminho feliz fica no fim, sem nenhuma chave em volta:
C#
Console.WriteLine(TentarAbrir(80, true, false));
Console.WriteLine(TentarAbrir(80, true, true));
static string TentarAbrir(int vida, bool temCartao, bool temEnergia)
{
if (vida <= 0) return "Você está morto.";
if (!temCartao) return "Você precisa do cartão.";
if (!temEnergia) return "Sem energia no prédio.";
return "Porta aberta.";
}
Saída esperada
Sem energia no prédio.
Porta aberta.
Mesmo comportamento, metade das linhas e nenhuma escada. Cada regra é uma linha que se lê sozinha. Essas primeiras verificações têm até nome: guard clauses (cláusulas de guarda).
2. Ternário para escolher um valor
Quando o if só serve para escolher entre dois valores, o operador ternário faz isso numa linha: condição ? valorSeVerdadeiro : valorSeFalso.
C#
int vida = 35;
string estado = vida < 50 ? "ferido" : "bem";
int velocidade = vida < 50 ? 3 : 5;
Console.WriteLine($"Você está {estado} e anda a {velocidade} m/s.");
Saída esperada
Você está ferido e anda a 3 m/s.
Use o ternário para valores, nunca para ações. E evite ternário dentro de ternário: com três ou mais opções, um switch fica mais claro.
3. Dê nome às condições
Uma condição grande no if obriga quem lê a decifrar a regra. Guarde o resultado numa variável bool com nome:
C#
int vida = 60, balas = 0, inimigosPerto = 3;
bool temFaca = true, ehNoite = true;
bool podeLutar = vida > 30 && (balas > 0 || temFaca);
bool situacaoPerigosa = inimigosPerto > 2 && ehNoite;
if (podeLutar && !situacaoPerigosa)
Console.WriteLine("Lute!");
else
Console.WriteLine("Melhor se esconder.");
Saída esperada
Melhor se esconder.
Compare com if (vida > 30 && (balas > 0 || temFaca) && !(inimigosPerto > 2 && ehNoite)). A regra é a mesma, mas os nomes explicam o porquê. Se a condição for usada em vários lugares, transforme-a num método, como PodeLutar().
4. Pattern matching: faixas sem repetir a variável

O C# moderno deixa testar faixas de valores com is e com a expressão switch, sem escrever o nome da variável a cada comparação:
C#
foreach (int vida in new[] { 100, 65, 20, 0 })
{
string estado = vida switch
{
0 => "morto",
< 30 => "crítico",
< 70 => "ferido",
_ => "saudável"
};
Console.WriteLine($"{vida,3}: {estado}");
}
int municao = 7;
if (municao is > 0 and < 10)
Console.WriteLine("Pouca munição, economize.");
Saída esperada
100: saudável
65: ferido
20: crítico
0: morto
Pouca munição, economize.
No switch, cada linha é testada em ordem e o _ é o "qualquer outro valor". Com is você pode juntar padrões com and, or e not: municao is > 0 and < 10 lê quase como português. O {vida,3} só alinha o número em 3 casas.
5. ?? para valores que podem faltar
Quando um texto pode ser null, o if de "se estiver vazio, use o padrão" vira um operador só, o ??:
C#
string? nomeDigitado = null;
string nome = nomeDigitado ?? "Sobrevivente";
Console.WriteLine($"Bem-vindo, {nome}.");
Saída esperada
Bem-vindo, Sobrevivente.
Leia a ?? b como "use a; se for nulo, use b". Existe também o ??=: nome ??= "Sobrevivente"; só preenche se estiver nulo.
Qual técnica usar
| Situação | Técnica |
|---|---|
| if dentro de if dentro de if | retorno antecipado |
| if só para escolher entre dois valores | ternário ? : |
| condição longa e difícil de ler | variável bool ou método com nome |
| várias faixas de um mesmo valor | expressão switch com padrões |
| "se for nulo, use este padrão" | ?? ou ??= |
Erros comuns
1. Comparar bool com true. if (temCartao == true) funciona, mas if (temCartao) diz o mesmo com menos ruído. Para o contrário, use !temCartao.
2. if que só devolve true ou false. if (vida > 0) return true; else return false; é só return vida > 0;.
3. Ordem errada no switch. Se < 70 vier antes de < 30, a vida 20 cai em "ferido", porque a primeira regra que combina vence. Vá do caso mais específico para o mais geral.
DESAFIO
Tente resolver antes de abrir a resposta. Sobreviveu? Vá para o próximo.
Reescreva com ternário:
string arma; if (balas > 0) arma = "pistola"; else arma = "faca";Ver resposta
string arma = balas > 0 ? "pistola" : "faca";Simplifique:
static bool EstaVivo(int vida) { if (vida > 0) { return true; } else { return false; } }Ver resposta
static bool EstaVivo(int vida) => vida > 0;Escreva uma expressão
switchque transforma o número de zumbis em "livre" (0), "cuidado" (1 a 3) e "fuja" (4 ou mais).Ver resposta
string alerta = zumbis switch { 0 => "livre", <= 3 => "cuidado", _ => "fuja" };
Conclusão
Código que só funciona é o mínimo. Código que se lê de primeira é o que você (e o seu eu do futuro) agradece. Retorno antecipado, nomes nas condições e pattern matching resolvem a maior parte dos if confusos.
📖 Revise a base: If, else e else if em C# e Switch em C#.
Comentários
Postar um comentário