Tratamento de Erros em C#: try/catch e Técnicas Avançadas para .NET

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Tratamento Avançado de Erros em C#: do básico try/catch aos padrões industriais

\n\n

Tratamento de erros não é apenas capturar exceções, mas a arte de projetar sistemas confiáveis. Em C# (.NET), desenvolvedores frequentemente se limitam à construção try/catch, mas a plataforma oferece mecanismos muito mais poderosos. Neste artigo, exploraremos técnicas avançadas: desde filtros de exceção até padrões de retry e passagem de contexto de erro.

\n\n

1. Filtros de Exceção: precisão em vez de placeholders

\n\n

Filtros de Exceção (Exception Filters), introduzidos no C# 6.0, permitem especificar uma condição para entrar no bloco catch sem relançar a exceção. Isso é muito mais limpo do que a abordagem clássica com if dentro do bloco.

\n\n
try\n{\n    // Código que pode lançar uma exceção\n    var result = ProcessData(input);\n}\ncatch (CustomException ex) when (ex.ErrorCode == 1001)\n{\n    // Processa apenas erros com código 1001\n    Log.Error($"Erro crítico: {ex.Message}");\n    throw; // Relança adiante, se necessário\n}\ncatch (CustomException ex) when (ex.IsRecoverable)\n{\n    // Erro recuperável — registra e continua\n    Log.Warning($"Erro recuperável: {ex.Message}");\n    RetryOperation();\n}
\n\n

Vantagens:

\n
    \n
  • Não requer um throw adicional para filtragem.
  • \n
  • Melhora a legibilidade e o desempenho (a pilha de chamadas não é corrompida).
  • \n
  • Permite combinar vários blocos catch com diferentes condições.
  • \n
\n\n

2. Padrão "Retry" e Polly

\n\n

Nem todos os erros são fatais. Para falhas temporárias (problemas de rede, bloqueios de BD), use o padrão de tentativas repetidas. Os recursos nativos do C# são limitados, portanto, recomenda-se a biblioteca Polly.

\n\n
using Polly;\nusing Polly.Retry;\n\n// Define a política de tentativas repetidas\nAsyncRetryPolicy retryPolicy = Policy\n    .Handle<HttpRequestException>() // Processa apenas erros HTTP\n    .WaitAndRetryAsync(\n        3, // Número de tentativas\n        retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), // Atraso exponencial\n        onRetry: (exception, timeSpan, retryCount, context) =>\n        {\n            Log.Warning($"Tentativa {retryCount} falhou. Repetindo em {timeSpan.Seconds} seg.");\n        });\n\n// Aplica a política\nawait retryPolicy.ExecuteAsync(async () =>\n{\n    var response = await httpClient.GetAsync("https://api.example.com/data");\n    response.EnsureSuccessStatusCode();\n});
\n\n

Importante: Não use retries infinitos. Sempre defina um número máximo de tentativas e use Circuit Breaker para proteger o sistema contra falhas em cascata.

\n\n

3. Passagem Correta de Exceções: throw vs throw ex

\n\n

Um dos erros mais comuns é a perda da pilha de chamadas. A diferença entre throw e throw ex é crítica para a depuração.

\n\n
try\n{\n    // ...\n}\ncatch (Exception ex)\n{\n    // INCORRETO: perde a pilha original\n    // throw ex;  \n\n    // CORRETO: preserva a pilha\n    throw;\n\n    // OU: adiciona contexto sem perder o original\n    // throw new ApplicationException("Erro no módulo X", ex);\n}
\n\n

Se precisar adicionar contexto, use ExceptionDispatchInfo (do namespace System.Runtime.ExceptionServices) para preservar precisamente a pilha ao relançar entre threads.

\n\n
ExceptionDispatchInfo.Capture(exception).Throw(); // Preserva a pilha original
\n\n

4. Exceções Personalizadas e Contexto de Erro

\n\n

Exceções padrão geralmente não carregam contexto de negócio. Crie suas próprias classes de exceção com propriedades adicionais.

\n\n
public class PaymentProcessingException : Exception\n{\n    public int OrderId { get; }\n    public dec                

Blogs

Book Recommendations