Capture de uma vez: como capturar múltiplas exceções em C# sem duplicar código
\n\nImagine: você está desenvolvendo um aplicativo que lida com arquivos, rede e bancos de dados. Em um único método, podem ocorrer FileNotFoundException, IOException ou UnauthorizedAccessException. A abordagem clássica — três blocos catch com o mesmo código interno — viola o princípio DRY (Don't Repeat Yourself) e transforma o código em um "macarrão".
A boa notícia: em C#, existem várias formas elegantes de capturar múltiplas exceções de uma só vez. Neste tutorial, vamos explorar todas as opções — das básicas às avançadas — e você aprenderá a escrever um código de tratamento de erros limpo e sustentável.
\n\nPor que isso é importante? Um cenário real
\n\nSuponha que você esteja criando um aplicativo de console para backup. Ele lê arquivos, compacta e os envia para um servidor remoto. Em cada etapa, diferentes exceções podem surgir:
\n\n- \n
- Leitura do arquivo:
FileNotFoundException,PathTooLongException\n - Compactação:
OutOfMemoryException\n - Envio:
HttpRequestException,TimeoutException\n
Se você escrever um catch separado para cada exceção com a mesma lógica de registro, o código ficará extenso. E se depois precisar alterar a lógica — terá que corrigir em três lugares. É aqui que saber capturar várias exceções de uma vez se torna essencial.
Método 1. Clássico: vários blocos catch (até C# 6)
\n\nO método mais simples e óbvio é escrever vários blocos catch em sequência. O próprio C# seleciona o bloco correto com base no tipo da exceção:
try\n{\n // Código que pode lançar diferentes exceções\n string content = File.ReadAllText(@"C:\\data\\config.txt");\n int value = int.Parse(content);\n await SendToServerAsync(value);\n}\ncatch (FileNotFoundException ex)\n{\n Console.WriteLine($"Arquivo não encontrado: {ex.Message}");\n LogError(ex);\n}\ncatch (FormatException ex)\n{\n Console.WriteLine($"Formato de dados inválido: {ex.Message}");\n LogError(ex);\n}\ncatch (HttpRequestException ex)\n{\n Console.WriteLine($"Erro de rede: {ex.Message}");\n LogError(ex);\n}\n\nVantagens: transparente, fácil de ler, permite tratar cada exceção de forma personalizada.
\nDesvantagens: se as ações forem idênticas — duplicação de código.
Método 2. Capturar múltiplas exceções em um único catch (C# 6+)
\n\nA partir do C# 6, você pode listar vários tipos de exceção usando | em um único bloco catch. Isso reduz a duplicação e mantém a legibilidade:
try\n{\n // Código arriscado\n}\ncatch (FileNotFoundException | FormatException | HttpRequestException ex)\n{\n Console.WriteLine($"Ocorreu um erro: {ex.Message}");\n LogError(ex);\n // Lógica adicional comum a todos os três tipos\n}\n\nImportante: todas as exceções devem ser compatíveis em hierarquia. Não é possível misturar, por exemplo, IOException e NullReferenceException — elas não têm um ancestral comum além de Exception. Mas no C# 6+ isso é permitido; o compilador simplesmente converte a variável ex para o tipo base comum.
Quando usar este método?
\n- \n
- Quando a lógica de tratamento é idêntica para todas as exceções. \n
- Quando você quer evitar blocos
ifouswitchaninhados. \n - Em métodos pequenos, onde a concisão é importante. \n
Método 3. Filtros de exceção (C# 6+)
\n\nOs filtros de exceção são um mecanismo poderoso que permite capturar exceções com base em condições usando a palavra-chave when. Você pode capturar a mesma exceção, mas com lógica diferente dependendo de suas propriedades:
try\n{