.NET -  Relançando (throw) exceções e a pilha de chamadas (revisão)


 Hoje vamos recordar a utilização da palavra-chave throw para relançar exceções e a pilha de chamadas.

Quando uma exceção é capturada, ela pode precisar ser relançada para ser tratada por métodos internos na pilha de chamadas. A maneira na qual um objeto Exception é relançado pode acarretar em mudanças nas informações que ele contém.

Um processo comum no tratamento de exceções é capturar a exceção, executar algum processamento e relançar a exceção para ser manipulada novamente chamando métodos.

O processamento realizado pode variar amplamente, dependendo das circunstâncias. Nos casos mais simples, você pode desejar extrair informações de propriedades de um objeto Exception e os detalhes de log para um arquivo ou um log de eventos. Em outros casos, você pode desejar construir uma nova exceção que contém mais informações, ou modificar a exceção existente, antes de lançar o objeto para ser tratado novamente.

Há duas maneiras nas quais você pode relançar uma exceção.

  1. A primeira é usar o palavra-chave throw sem nenhum parâmetro dentro de um bloco catch. Usar esta abordagem mantém todas as informações no âmbito da exceção, incluindo as propriedades StackTrace e TargetSite.
    • A propriedade StackTrace é importante porque ela mostra todas as chamadas que foram feitas entre o método atual e o local onde ocorreu a exceção.
    • A propriedade TargetSite contém o nome do membro que originalmente gerou a exceção.

Podemos demonstrar isto através da criação de um aplicativo console que contém o código a seguir.

Module Module1
    Sub Main()
        Try
            RelancarMetodo()
        Catch ex As Exception
            Console.WriteLine(ex.TargetSite)
            Console.WriteLine(ex.StackTrace)
        End Try
    End Sub
    Private Sub RelancarMetodo()
        Try
            FalhaOriginal()
        Catch ex As Exception
            Throw
        End Try
    End Sub
    Private Sub FalhaOriginal()
        Throw New Exception("Ocorreu um erro...!")
    End Sub
End Module
 
  class Program
    {
        static void Main(string[] args)
        {
            try
            {
                RelancarMetodo();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.TargetSite);
                Console.WriteLine(ex.StackTrace);
            }
            Console.ReadKey();
        }
        private static void RelancarMetodo()
        {
            try
            {
                FalhaOriginal();
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        private static void FalhaOriginal()
        {
            throw new Exception("Ocorreu um erro...!");
        }
    }

Como estamos usando somente  a palavra-chave throw o resultado de stack trace e target site são baseados na localização da exceção original. Ambos exibem "FalhaOriginal" como o ponto de partir da exceção:

  1. A segunda maneira é usar a palavra-chave throw seguida de exeção : Ex:  throw ex.

    Se você criar uma nova exceção com base em uma que você já tiver capturado, você pode lançar a substituição, especificando-a após o comando throw.

    Normalmente você não deve usar essa abordagem para relançar uma exceção porque as propriedades StackTrace e TargetSite são redefinidas. Isto significa que a exceção vai parecer que foi originada a partir do método que a relançou.

    Para demonstrar a diferença, substitua a linha "throw" em RelancarMetodo por "throw ex":

Executando novamente os projetos iremos obter outro resultado:

Observe que agora não existe nenhuma menção ao método FalhaOriginal nem em stack trace nem em target site.

Recursos usados:

Nota: Baixe e use a versão Community 2015 do VS ela é grátis e é equivalente a versão Professional.

Pegue o projeto completo aqui : VBNET_CSharp_throw.zip

Deus nunca foi visto por alguém. O Filho unigênito (Jesus), que está no seio do Pai, esse o revelou.
João 1:18

Referências:


José Carlos Macoratti