Introdução ao tratamento de erros em C#
Em qualquer aplicação, especialmente em sistemas corporativos complexos na plataforma .NET, erros são inevitáveis. O usuário pode inserir dados incorretos, um arquivo pode estar indisponível ou uma conexão de rede pode ser interrompida. Em vez de permitir que o programa termine abruptamente, um desenvolvedor competente utiliza o mecanismo de tratamento de exceções.
Em C#, a base desse mecanismo é a construção try/catch/finally. No entanto, as capacidades da linguagem não se limitam a isso: existem os operadores using e throw, além da possibilidade de criar tipos de exceção personalizados. Neste artigo, abordaremos detalhadamente todos os aspectos-chave do tratamento de erros em C# (.NET), para que seu código seja não apenas confiável, mas também legível.
1. Construção básica: try, catch e finally
Esta é a base com a qual se inicia o aprendizado sobre exceções. O bloco try contém o código que potencialmente pode causar um erro. O bloco catch captura a exceção e a trata. O bloco finally é sempre executado, independentemente de ter ocorrido um erro ou não — ele é ideal para liberar recursos (fechar arquivos, conexões).
Sintaxe e exemplo
using System;using System.IO;
class Program{ static void Main() { try { Console.Write("Digite o caminho do arquivo: "); string path = Console.ReadLine(); string content = File.ReadAllText(path); Console.WriteLine("Conteúdo do arquivo:"); Console.WriteLine(content); } catch (FileNotFoundException ex) { Console.WriteLine($"Erro: Arquivo não encontrado. {ex.Message}"); } catch (UnauthorizedAccessException ex) { Console.WriteLine($"Erro: Sem acesso ao arquivo. {ex.Message}"); } catch (Exception ex) // Captura genérica de todas as outras exceções { Console.WriteLine($"Erro desconhecido: {ex.Message}"); } finally { Console.WriteLine("Bloco finally executado. Liberando recursos (se necessário)."); } }}Pontos importantes:
- A ordem dos blocos catch é importante: primeiro devem ser capturadas exceções mais específicas (por exemplo,
FileNotFoundException), depois as mais genéricas (Exception). Se o bloco genérico for colocado primeiro, os blocos mais específicos nunca serão alcançados. - O bloco finally não é obrigatório. Se você não precisa liberar recursos de forma garantida, pode omiti-lo.
- Não capture
Exceptionsem necessidade. Se você não sabe como tratar um erro, é melhor deixar o programa falhar — isso ajudará a identificar o problema durante o desenvolvimento.
2. Liberação de recursos com using
Embora finally seja uma ferramenta poderosa, escrevê-lo toda vez para coisas como fechar arquivos ou conexões de banco de dados é tedioso. Para objetos que implementam a interface IDisposable, o C# possui o operador using. Ele garante a chamada do método Dispose() ao sair do bloco, mesmo que uma exceção tenha ocorrido.
Comparação de abordagens
Sem using (liberação manual):
StreamReader reader = null;try{ reader = new StreamReader("data.txt"); string line = reader.ReadLine(); // ... trabalho com reader}finally{ if (reader != null) reader.Dispose();}Com o uso de using:
using (StreamReader reader = new StreamReader("data.txt")){ string line = reader.ReadLine(); // ... trabalho com reader}// Dispose() será chamado automaticamente