DEV Community

Cover image for Melhorando o tratamento de exceções no C#
Víctor Fructuoso
Víctor Fructuoso

Posted on

6

Melhorando o tratamento de exceções no C#

Um dos meus principais lemas como programador é:

Se você precisar debugar o código para achar um BUG, é por que o código não está bem escrito.

Neste artigo, abordo três formas de relançar uma exceção e quais as principais diferências entre elas.

Antes de falar sobre a Exception em si, precisamos entender a propriedade mais importante que ela tem... (pausa dramática)

StackTrace

Esta certamente é a propriedade mais importante de qualquer Exception, pois através dela é possível entender toda a "pilha de chamadas" que foi realizada, até o exato ponto onde a exceção foi lançada.

Daí chegamos ao ponto que muitos programadores iniciantes costumam errar...

É muito comum ver tratamentos de erro com algo mais ou menos assim:

_logger.LogError(ex.Message);
Enter fullscreen mode Exit fullscreen mode

Quando isso é feito, estamos jogando fora praticamente toda e qualquer informação que pode nos ajudar a rastrear o erro através do Log.

Neste caso, o ideal seria utilizar algo como o código abaixo:

_logger.LogError(ex, ex.Message);
Enter fullscreen mode Exit fullscreen mode

Neste link temos a documentação oficial da Microsoft com todas as implementações do método de extensão LogError da interface ILogger.

Caso você precise obter os dados da exceção para usar em algum outro local, é preferível ainda usar o ToString(), que entrega o Message concatenado com o StackTrace, fornecendo assim, um detalhamento completo do erro.

O cenário

Para ilustrar as três formas que serão abordadas, vamos entender o seguinte cenário:

Console.WriteLine("Um exemplo de como tratar exceções!");
var objetoA = new ClasseA();
objetoA.UmMetodo();
internal class ClasseA
{
public void UmMetodo()
{
try
{
var objetoB = new ClasseB();
objetoB.OutroMetodo();
}
catch (Exception ex)
{
//...
}
}
}
internal class ClasseB
{
public void OutroMetodo() => throw new NotImplementedException();
}
internal class CustomException : Exception
{
public CustomException(Exception innerException) : base(message: "Esta é uma exceção customizada!", innerException) { }
}
view raw Completo.cs hosted with ❤ by GitHub

A ClasseB possuí o método "OutroMetodo" não implementado.
A ClasseA possui o método "UmMetodo" que chama o método da ClasseB, que por sua vez lançará a exceção "NotImplementedException".

Veremos as três formas de implementar o tratamento de exceção na ClasseA, e o impacto de cada uma delas no Log da aplicação.

throw

Neste caso, a exceção é relançada mantendo o StackTrace completo.

Console.WriteLine("Um exemplo de como tratar exceções!");
var objetoA = new ClasseA();
objetoA.UmMetodo();
internal class ClasseA
{
public void UmMetodo()
{
try
{
var objetoB = new ClasseB();
objetoB.OutroMetodo();
}
catch
{
//...
throw;
}
}
}
view raw Throw.cs hosted with ❤ by GitHub

Resultado:

System.NotImplementedException: The method or operation is not implemented.
   at ClasseB.OutroMetodo() in Program.cs:line 23
   at ClasseA.UmMetodo() in Program.cs:line 12
   at Program.<Main>$(String[] args) in Program.cs:line 3
Enter fullscreen mode Exit fullscreen mode

throw ex

Nesta situação a exceção é relançada, mas diferentemente do cenário anterior o StackTrace do que aconteceu antes deste relançamento é descartado.

Em alguns casos isso pode ser útil, para que possamos ocultar algum detalhe do componente ou até mesmo tornar o log menor e mais objetivo.

Console.WriteLine("Um exemplo de como tratar exceções!");
var objetoA = new ClasseA();
objetoA.UmMetodo();
internal class ClasseA
{
public void UmMetodo()
{
try
{
var objetoB = new ClasseB();
objetoB.OutroMetodo();
}
catch (Exception ex)
{
//...
throw ex;
}
}
}
view raw ThrowEx.cs hosted with ❤ by GitHub

Notem que neste caso, nenhuma referência a ClasseB é feita.

Resultado:

System.NotImplementedException: The method or operation is not implemented.
   at ClasseA.UmMetodo() in Program.cs:line 17
   at Program.<Main>$(String[] args) in Program.cs:line 3
Enter fullscreen mode Exit fullscreen mode

CustomException

Neste caso é criado um tipo de exceção customizado, este novo tipo é lançado, passando a exceção original como InnerException.

Console.WriteLine("Um exemplo de como tratar exceções!");
var objetoA = new ClasseA();
objetoA.UmMetodo();
internal class ClasseA
{
public void UmMetodo()
{
try
{
var objetoB = new ClasseB();
objetoB.OutroMetodo();
}
catch (Exception ex)
{
//...
throw new CustomException(ex);
}
}
}

Desta forma o StackTrace é dividido em dois, tornando mais claro o que aconteceu.

Resultado:

CustomException: Esta é uma exceçao customizada!
 ---> System.NotImplementedException: The method or operation is not implemented.
   at ClasseB.OutroMetodo() in Program.cs:line 23
   at ClasseA.UmMetodo() in Program.cs:line 12
   --- End of inner exception stack trace ---
   at ClasseA.UmMetodo() in Program.cs:line 17
   at Program.<Main>$(String[] args) in Program.cs:line 3
Enter fullscreen mode Exit fullscreen mode

Conclusão

Não existe método certo ou método errado, o importante é entender o funcionamento de cada forma de trabalho, para que o detalhamento da exceção seja apresentada da melhor forma possível. Isso fará toda a diferença no momento de identificar um bug, inclusive aquele que você não consegue reproduzir na sua máquina.

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

Top comments (1)

Collapse
 
mateuslemos profile image
Mateus Lemos

Show de bola esse artigo Fructuoso, simples e direto ao ponto. Me acrescentou conhecimento!

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay