Verificação de parâmetros nulos em C# 10 e .NET 6 em 10 minutos ou menos
Ao trabalhar em C#, é comum os desenvolvedores se depararem com argumentos nulos sendo passados para os métodos. Isso pode levar a comportamentos inesperados, erros de tempo de execução e até mesmo exceções não tratadas, caso não sejam devidamente gerenciadas. Em seu vídeo " Verificações de parâmetros nulos em C# 10 e .NET 6 em 10 minutos ou menos ", Tim Corey explica como o C# 10 simplificou o tratamento de valores nulos usando a classe ArgumentNullException.
Neste artigo, vamos analisar o vídeo exatamente como Tim explica, para entender como funcionam as verificações de valores nulos e como elas foram aprimoradas no C# moderno.
Preparando o terreno – Verificando parâmetros nulos
Tim começa criando um aplicativo de console .NET 6 simples para mostrar como as verificações de parâmetros nulos são tratadas em C#. Ele remove o código repetitivo e declara uma variável de string que pode ser anulada:
string? info = null;
string? info = null;
Este objeto nulo representa um cenário em que uma chamada de método pode receber um argumento que não foi instanciado corretamente. Tim então define um método simples:
void SayHi(string message)
{
Console.WriteLine($"Olá {message}");
}
void SayHi(string message)
{
Console.WriteLine($"Olá {message}");
}
Ele passa a variável info para o método:
SayHi(info);
SayHi(info);
Quando o programa é executado, a saída simplesmente exibe:
Olá
Nenhuma exceção ocorre porque a concatenação de strings aceita um valor nulo e o trata como uma string vazia. Mas, como Tim destaca, na maioria dos métodos do mundo real, isso pode causar situações propensas a erros, onde uma referência nula leva a problemas subsequentes ou a uma exceção NullReferenceException mais adiante na pilha de chamadas.
Para criar um código robusto, os desenvolvedores devem validar os argumentos e garantir que qualquer método espere uma entrada válida e não nula.
Verificação de nulo tradicional antes do C# 10
Tim explica que, antes do C# 10, a boa prática era verificar manualmente os parâmetros e lançar uma exceção ArgumentNullException quando necessário. Dentro do método SayHi, ele acrescenta:
if (message is null)
throw new ArgumentNullException(nameof(message));
if (message is null)
throw new ArgumentNullException(nameof(message));
Essa verificação garante que, se um argumento nulo for passado, o programa lance imediatamente uma nova instância da classe ArgumentNullException.
Quando Tim executa o código, a mensagem de erro é exibida claramente:
System.ArgumentNullException: Value cannot be null. (Parameter 'message')
System.ArgumentNullException: Value cannot be null. (Parameter 'message')
Essa exceção não tratada indica que o método recebeu um argumento inválido. O nome do parâmetro — neste caso, 'message' — é exibido automaticamente na saída, ajudando o desenvolvedor a identificar exatamente qual argumento causou o problema.
Tim observa que essa verificação manual funciona perfeitamente bem no .NET Framework e em versões anteriores do .NET Core . No entanto, torna-se prolixo e repetitivo ao lidar com múltiplos parâmetros. Cada parâmetro adicional que precisa de validação acrescenta três ou quatro linhas de código, poluindo o corpo do método.
A abordagem simplificada em C# 10 – ArgumentNullException.ThrowIfNull()
Neste ponto, Tim apresenta a sintaxe moderna do C# 10. Em vez de escrever várias linhas para cada parâmetro, os desenvolvedores agora podem escrever uma única linha para verificar se o valor é nulo:
ArgumentNullException.ThrowIfNull(message);
ArgumentNullException.ThrowIfNull(message);
Tim explica que essa linha de comando executa internamente a mesma lógica de validação. Se o argumento passado for nulo, o método lança uma exceção automaticamente — assim como antes — mas com uma sintaxe muito mais limpa.
Ao executar o programa novamente, a seguinte saída é exibida:
System.ArgumentNullException: Value cannot be null. (Parameter 'message')
System.ArgumentNullException: Value cannot be null. (Parameter 'message')
O comportamento permanece idêntico, mas agora a sintaxe foi simplificada. Não é necessário instanciar manualmente um novo objeto ArgumentNullException usando um construtor ou especificar o parâmetro paramName manualmente. O nome do parâmetro do chamador é inferido automaticamente pelo compilador.
Tim enfatiza que essa melhoria economiza tempo e reduz a probabilidade de erro humano ao referenciar o nome de parâmetro errado.
Exemplo: Vários parâmetros
Tim então compara o método tradicional com o novo ao lidar com múltiplos parâmetros.
Antes do C# 10, um desenvolvedor poderia escrever:
if (name is null)
throw new ArgumentNullException(nameof(name));
if (email is null)
throw new ArgumentNullException(nameof(email));
if (password is null)
throw new ArgumentNullException(nameof(password));
if (name is null)
throw new ArgumentNullException(nameof(name));
if (email is null)
throw new ArgumentNullException(nameof(email));
if (password is null)
throw new ArgumentNullException(nameof(password));
Com o aprimoramento do C# 10 , as mesmas verificações agora podem ser escritas de forma mais concisa:
ArgumentNullException.ThrowIfNull(name);
ArgumentNullException.ThrowIfNull(email);
ArgumentNullException.ThrowIfNull(password);
ArgumentNullException.ThrowIfNull(name);
ArgumentNullException.ThrowIfNull(email);
ArgumentNullException.ThrowIfNull(password);
Essa melhoria não se resume apenas a menos linhas — ela torna seus métodos mais claros, legíveis e fáceis de manter. Tim observa que, se o seu método espera três parâmetros, agora você precisa apenas de três verificações de nulo, em vez de doze linhas de código.
Por que isso importa – Código mais seguro e robusto
Tim destaca que, embora passar manualmente um valor nulo para uma string em uma demonstração possa não ser realista, isso representa problemas do mundo real. APIs, entradas do usuário, processos de desserialização ou operações que retornam objetos podem gerar objetos nulos inesperadamente.
Ao adicionar verificações de nulo no início de um método, você evita comportamentos inesperados e falha rapidamente — o que significa que o programa lança uma exceção no início da pilha de chamadas antes que o problema se propague.
Ele também menciona que essa nova sintaxe ajuda a manter padrões consistentes de tratamento de erros em todos os seus métodos. Isso incentiva a escrita de código robusto e resiliente a entradas inválidas e objetos não instanciados.
Detalhes da exceção ArgumentNullException
Tim destaca que ArgumentNullException faz parte do namespace System e herda da classe ArgumentException. É lançada quando uma referência nula é passada para um método que não a aceita como um argumento válido.
Normalmente inclui:
-
O nome do parâmetro que causou o problema.
-
Uma mensagem de erro clara: "O valor não pode ser nulo."
- A pilha de chamadas, mostrando onde a exceção ocorreu.
O exemplo de Tim demonstra como o .NET 6 continua seguindo esse comportamento, ao mesmo tempo que aprimora a sintaxe.
Ele também observa brevemente que os desenvolvedores podem combinar essas verificações com outros recursos, como o operador de coalescência nula (??) ou valores padrão para fornecer lógica de fallback — por exemplo:
message ??= "Default message";
message ??= "Default message";
Isso permite que um método atribua um valor padrão em vez de lançar uma exceção, se desejado.
Importância da verificação de valores nulos no tratamento de erros
Tim lembra aos desenvolvedores que, embora o C# agora suporte tipos de referência anuláveis, as verificações de nulo em tempo de execução ainda são essenciais. O compilador não consegue detectar todos os problemas de referência nula, especialmente quando os dados vêm de fontes externas ou de métodos fora do seu controle.
Ele enfatiza que é uma boa prática verificar os argumentos e lançar uma exceção ArgumentNullException quando apropriado, garantindo que o método seja executado somente quando as entradas forem válidas. Isso minimiza erros em tempo de execução, simplifica o tratamento de erros e evita falhas silenciosas.
Concluindo e olhando para o futuro
Ao concluir, Tim observa que o C# 11 introduzirá ainda mais melhorias, mas, por enquanto, ArgumentNullException.ThrowIfNull() é uma das melhores pequenas melhorias para tratamento de erros e segurança de código no .NET 6.
Ele incentiva os desenvolvedores a experimentarem essa abordagem em seus próprios projetos e a verem como seus métodos ficam muito mais limpos. Ele termina com uma pergunta: "O que vocês acham dessa mudança no C# 10?"
Considerações finais
O vídeo de Tim Corey deixa claro que o método ArgumentNullException.ThrowIfNull() é uma melhoria simples, porém poderosa, no C# 10. Ele reduz o código manual propenso a erros, garante argumentos válidos e faz com que seus programas falhem rapidamente quando um argumento nulo for passado.
Ao usar esse método de forma consistente, os desenvolvedores podem criar um código robusto, legível e de fácil manutenção, que lida com exceções de forma adequada e evita bugs sutis de referência nula.
Resumindo, sempre que seu método espera um parâmetro válido e você deseja evitar argumentos nulos, siga o exemplo de Tim Corey e use:
ArgumentNullException.ThrowIfNull(parameterName);
ArgumentNullException.ThrowIfNull(parameterName);
É uma forma mais limpa, segura e moderna de proteger seu código contra valores nulos e erros de tempo de execução no .NET 6 e versões posteriores.
