Tratamento de erros em C#: try/catch e técnicas avançadas

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 de erros em C#: do try/catch às técnicas profissionais



No mundo do desenvolvimento industrial em C# e .NET, o tratamento de erros não é apenas uma construção try/catch. É uma filosofia completa que define a confiabilidade, legibilidade e tolerância a falhas do seu código. Em um nível avançado, o desenvolvedor não deve apenas capturar exceções, mas também projetá-las, filtrá-las, registrá-las e restaurar o estado da aplicação de forma competente. Neste artigo, abordaremos os principais aspectos do tratamento de erros em C# que o ajudarão a escrever um código mais profissional e de maior qualidade.



1. Aprofundando em try/catch/finally: gerenciamento de recursos e contexto



A construção básica try-catch-finally é familiar a todos, mas vamos analisá-la de um ângulo diferente. O principal objetivo do bloco finally é garantir a liberação de recursos, mesmo que ocorra uma exceção. Nas versões modernas do C#, usa-se mais frequentemente using para isso, mas o finally continua indispensável ao trabalhar com recursos não gerenciados ou lógica de encerramento complexa.



public void ProcessFile(string path){    FileStream? fileStream = null;    try    {        fileStream = File.OpenRead(path);        // Lógica de processamento do arquivo    }    catch (FileNotFoundException ex)    {        // Tratamento específico: arquivo não encontrado        Log.Error($"Arquivo {path} não encontrado: {ex.Message}");        throw; // Relança a exceção, preservando a pilha de chamadas    }    catch (UnauthorizedAccessException)    {        Log.Warn($"Sem acesso ao arquivo: {path}");        // Pode executar uma ação alternativa sem relançar a exceção        return;    }    finally    {        // Liberação garantida do recurso        fileStream?.Dispose();    }}


Observe o uso de throw; (sem argumento) — este é um ponto crucial. Ao contrário de throw ex;, a construção throw; preserva a pilha de chamadas original, o que é fundamental para a depuração. Nunca use throw ex; em projetos reais, pois isso destrói a informação sobre o local de origem do erro.



2. Exceções personalizadas: projetando um modelo de domínio de erros



Em aplicações grandes, as exceções padrão do .NET muitas vezes não são suficientes. Criar suas próprias classes de exceção permite transmitir com precisão o contexto do erro e simplifica o tratamento nos níveis superiores. Uma boa exceção personalizada deve ser serializável, conter uma mensagem significativa e carregar informações adicionais (por exemplo, o identificador da entidade).



[Serializable]public class OrderProcessingException : Exception{    public int OrderId { get; }    public string FaultyStep { get; }

public OrderProcessingException(int orderId, string faultyStep, string message) : base(message) { OrderId = orderId; FaultyStep = faultyStep; }

public OrderProcessingException(int orderId, string faultyStep, string message, Exception inner) : base(message, inner) { OrderId = orderId; FaultyStep = faultyStep; }

// Construtor para desserialização protected OrderProcessingException( System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { OrderId = info.GetInt32(nameof(OrderId)); FaultyStep = info.GetString(nameof(FaultyStep)) ?? string.Empty; }

public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { base.GetObjectData(info, context); info.AddValue(nameof(OrderId), OrderId); info.AddValue(nameof(FaultyStep), FaultyStep); }}

// Usopublic void ValidateOrder(int orderId){ try {

Blogs

Book Recommendations