quarta-feira, 26 de maio de 2010

Dica para tratamento de exceção no C#

Estava com um problema no tratamento de exceções do C#, pois em alguns pontos da aplicação a mensagem retornada dentro da propriedade Message da classe Exception não era a mensagem original gerada no ponto onde ocorreu a falha, isso me levou a efetuar pesquisas, e identifiquei o seguinte...

Uma prática muito utilizada é criarmos nossos try/catch e não tratarmos as exceções nas camadas de baixo nível da aplicação (como por exemplo a camada de banco de dados), desta forma somente forçamos o retorno da exceção para a camada de alto nível (por exemplo a camada de interface) para que ela faça o tratamento.Veja:

public void Teste()
{
   try
   {
      throw new DivideByZeroException("Uma exceção de divisão por zero foi forçada.");
   }
   catch (DivideByZeroException ex)
   {
      throw (ex);
   }
   catch (Exception ex)
   {
      throw (ex);
   }
}


Nos catch´s utilizamos o throw para reportar a exceção para a camada executora, assim na hora de tratarmos a exceção na camada de alto nível, não temos a certeza de qual o tipo de exceção que está sendo retornado, se IOException, se DivideByZeroException, se Exception, desta forma efetuamos o tratamento com a classe genérica que é a Exception para evitar falhas e interrupção da execução do aplicativo. Exemplo:



try
{
   oObj.Teste();
}
catch (Exception ex)
{
   global::System.Windows.Forms.MessageBox.Show(ex.Message);
}


O grande problema é que na ex.Message pode ocorrer de termos como retorno o seguinte conteúdo: "Exception has been thrown by the target of an invocation" e não o erro de divisão por zero forçado no código de exemplo anterior "Uma exceção de divisão por zero foi forçada.", deixando difícil a identificação da exceção para o usuário como para o programador.



Por não sabermos o tipo de exceção que será retornado e não termos que tratar todos os tipos de exceção existentes, pois são vários, podemos utilizar a seguinte solução:



try
{
   oObj.Teste();
}
catch (Exception ex)
{
   global::System.Windows.Forms.MessageBox.Show((ex.InnerException != null ? ex.InnerException.Message : ex.Message));
}


Sempre que não tivermos a certeza do tipo de exceção que será retornado, tratemos ela utilizando o conteúdo da InnerException, se for diferente de null, pegamos o conteúdo da propriedade Message dela, caso contrário continuamos com o Message da Exception.



Reforço que nem sempre a InnerException possui conteúdo, por isso que verificamos se ela é diferente de null, se for basta pegar o seu conteúdo que vamos ter o a informação original da exceção.

Nenhum comentário:

Postar um comentário