Pular para o conteúdo
.NETExceções customizadas
Módulo 02Fundamentos de Aplicação

Exceções customizadas

intermediario 22 min de leitura·Atualizado · .NET 9
Resumo

Exceções próprias tornam erros de domínio explícitos e fáceis de tratar. Uma ProdutoNaoEncontradoException comunica muito mais que uma Exception genérica — e permite mapear o erro para o status HTTP certo na API.

1. Objetivos de Aprendizagem#

  • Criar exceções derivadas de Exception.
  • Modelar erros de domínio com hierarquia própria.
  • Preservar a exceção original com innerException.

2. Pré-requisitos#

  • try/catch/finally (tópico 10.1).

3. Conceito#

Você cria uma exceção herdando de Exception (ou de uma base sua). O porquê: dar nome e semântica aos erros do seu domínio, permitindo que camadas superiores (ex.: um middleware de erros na API) decidam como respondê-los (404, 422, etc.).

Boas práticas de design:

  • Sufixo Exception no nome.
  • Uma base comum de domínio (ex.: DominioException) e derivadas específicas.
  • Construtores que aceitam mensagem e, opcionalmente, a exceção interna.

4. Mão na Massa#

4.1. Setup#

Shell
dotnet new console -n Catalog.CustomEx
cd Catalog.CustomEx

4.2. Implementação Passo a Passo#

  1. Base + derivadas:
C#
public abstract class DominioException : Exception
{
    protected DominioException(string mensagem) : base(mensagem) { }
}

public sealed class ProdutoNaoEncontradoException : DominioException
{
    public ProdutoNaoEncontradoException(Guid id)
        : base($"Produto {id} não encontrado.") { }
}

public sealed class PrecoInvalidoException : DominioException
{
    public PrecoInvalidoException(decimal valor)
        : base($"Preço inválido: {valor}.") { }
}
  1. Uso e captura pela base:
C#
Produto Buscar(Guid id) =>
    throw new ProdutoNaoEncontradoException(id);

try
{
    Buscar(Guid.NewGuid());
}
catch (DominioException ex)   // captura qualquer erro de domínio
{
    Console.WriteLine($"Erro de domínio: {ex.Message}");
}

record Produto(Guid Id);
  1. Preservando a origem (innerException):
C#
try { /* chamada externa */ }
catch (Exception original)
{
    throw new DominioException2("Falha ao integrar", original);
}

public class DominioException2 : Exception
{
    public DominioException2(string m, Exception inner) : base(m, inner) { }
}

4.3. Executando#

Shell
dotnet run

5. Exemplo Completo#

Com uma base DominioException, o middleware de erros da API pode mapear ProdutoNaoEncontradoException → 404 e PrecoInvalidoException → 422 num só lugar — exatamente o padrão do Módulo 05 do curso de Web API.

6. Boas Práticas e Armadilhas#

FaçaEvite
Criar uma base de domínio e derivadas específicasLançar Exception genérica para tudo
Preservar a exceção interna ao "re-embrulhar"Descartar o innerException e perder o rastro
Usar exceções para erros de regra, não para fluxo comumCriar dezenas de exceções triviais sem necessidade
Atenção

ao capturar e relançar, use throw; (sem o objeto) para preservar o stack trace. throw ex; reinicia o rastro e esconde a origem.

7. Segurança e Produção#

  • Não exponha detalhes internos (stack trace, SQL) nas mensagens que chegam ao cliente. Mensagens de exceção são para logs; a resposta ao usuário deve ser sóbria.

8. Exercícios#

  • Fácil: crie uma CategoriaNaoEncontradaException.
  • Médio: organize suas exceções sob uma base comum e capture pela base.
  • Desafio: relance uma exceção externa embrulhada numa de domínio, preservando a original.

9. Resumo#

Exceções customizadas dão semântica aos erros de domínio e permitem mapear respostas HTTP num só lugar. Use uma base comum, preserve innerException e relance com throw;.

10. Próximos Passos#

A seguir, as boas práticas gerais de tratamento de exceções.

11. Referências#

10-02 — Exceções customizadas | Curso ASP.NET Core