Tratamento de Erros em C#: try/catch e muito mais: de A a Z
Qualquer aplicação, mesmo escrita pelo desenvolvedor mais experiente, pode enfrentar situações imprevistas: falha de rede, ausência de arquivo no disco, divisão por zero ou entrada de dados inválida. Em C# (.NET), para gerenciar tais situações, utiliza-se o mecanismo de exceções (exceptions). Neste artigo, abordaremos tudo o que você precisa saber sobre tratamento de erros: desde a construção básica try/catch até a criação de seus próprios tipos de exceção e as melhores práticas modernas.
1. Fundamentos: construção try/catch/finally
Em C#, o tratamento de erros é construído em torno de três blocos principais: try, catch e finally.
- try — contém o código que pode lançar uma exceção.
- catch — captura e trata uma exceção específica.
- finally — é executado sempre, independentemente de ter ocorrido uma exceção ou não (geralmente para liberar recursos).
try{ int[] numbers = { 1, 2, 3 }; Console.WriteLine(numbers[5]); // IndexOutOfRangeException}catch (IndexOutOfRangeException ex){ Console.WriteLine($"Erro: {ex.Message}");}finally{ Console.WriteLine("O bloco finally é sempre executado.");}Você pode usar vários blocos catch para diferentes tipos de exceções. O tratamento ocorre de cima para baixo, portanto, exceções mais específicas devem ser colocadas antes das mais genéricas.
try{ // código perigoso}catch (DivideByZeroException ex){ Console.WriteLine("Divisão por zero!");}catch (Exception ex) // captura genérica{ Console.WriteLine($"Ocorreu um erro: {ex.Message}");}2. Geração de exceções: operador throw
Às vezes, você precisa sinalizar explicitamente uma situação incorreta. Para isso, utiliza-se o operador throw. Você pode lançar tanto uma exceção padrão quanto uma personalizada.
public void ValidateAge(int age){ if (age < 0 || age > 150) { throw new ArgumentOutOfRangeException(nameof(age), "A idade deve estar entre 0 e 150."); } Console.WriteLine("Idade válida.");}Existe também a construção throw; (sem argumentos) — ela é usada dentro de um bloco catch para relançar a mesma exceção. Isso é útil quando você deseja registrar o erro em log, mas não quer suprimi-lo.
try{ // código}catch (Exception ex){ Log.Error(ex); // registro em log throw; // relançamento — a exceção continua propagando}3. Criando exceções personalizadas (Custom Exceptions)
Para a lógica de negócios, geralmente é mais conveniente usar seus próprios tipos de exceção. Isso torna o código mais legível e permite tratar erros específicos com precisão.
Regras para criar uma exceção personalizada:
- Herdar da classe
Exception(ou deApplicationException, mas é melhor herdar deException). - Implementar três construtores padrão (sem parâmetros, com mensagem, com mensagem e exceção interna).
- Recomenda-se adicionar o sufixo
Exceptionao nome da classe.
public class UserNotFoundException : Exception{ public UserNotFoundException() { }
public UserNotFoundException(string message) : base(message) { }
public UserNotFoundException(string message, Exception inner) : base(message, inner) { }}
// Usothrow new UserNotFoundException("Usuário com ID 123 não encontrado.");4. Melhores práticas: como não prejudicar a si mesmo e ao projeto
Tratamento de erros não é apenas envolver tudo em try/catch. Aqui estão algumas regras de ouro a serem seguidas em C# (.NET):