Postergando o Disparo de Exceções


Utilizamos o bloco try/catch para conseguir tratar erro onde ele acontece, ou seja, envolvemos no bloco try o trecho de código que pode dar erro, e se ele acontecer, o bloco catch, opcionalmente, pode capturar o erro e o tratar, dando uma mensagem customizada, realizando o log, etc.

Na grande maioria das vezes quando trabalhamos na construção de uma biblioteca, não devemos tratar o erro no local, pois o ideal é deixar que ele seja disparado e propagado, para que assim o consumidor tenha a chance de saber o porque aquele erro aconteceu. E, se desejar interceptar a exceção dentro da biblioteca, é necessário redisparar a exceção preservando a stack trace, que é onde é armazenado todo o caminho (classes e métodos) até onde o erro de fato ocorreu. O código abaixo exibe como fazer isso:

try
{
    //Algum Código
}
catch (Exception ex)
{
    //Log, Tratamento

    throw;
}

Quando o throw for executado, o .NET dispara a exceção que ocorreu mantendo toda a stack trace, o que é essencial para que o consumidor possa entender o que houve. Só que se quisermos executar mais algum código a partir desta linha e postergar o disparo da exceção, não é possível, pois essa keyword tem uma tratativa especial pelo .NET Framework e aborta a execução das linhas que estão na sequência.

Isso inclusive era uma dificuldade do time do .NET Framework para conseguir fazer com que as exceções que ocorriam dentro dos métodos assíncronos fossem propagados sem perder as informações (stack trace). Para resolver isso, foi criado uma classe chamada ExceptionDispatchInfo (namespace System.Runtime.ExceptionServices), que através do método estático Capture, recebe como parâmetro e armazena a exceção que ocorreu, e mais tarde, quando desejar, podemos redispará-la através do método Throw, conforme é mostrado abaixo:

private static string LerConteudo(string nomeDoArquivo)
{
    var conteudo = string.Empty;
    ExceptionDispatchInfo erro = null;

    try
    {
        conteudo = File.ReadAllText(nomeDoArquivo);
    }
    catch (Exception ex)
    {
        erro = ExceptionDispatchInfo.Capture(ex);
    }

    //Algum outro código aqui

    if (erro != null) erro.Throw();

    return conteudo;
}

Unhandled Exception: System.IO.FileNotFoundException: Could not find file ‘C:UsersIsraelDesktopConsoleApplication1ConsoleApplication1binDebugTeste.txt’.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
   at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize, Boolean checkHost)
   at System.IO.File.InternalReadAllText(String path, Encoding encoding, Boolean checkHost)
   at System.IO.File.ReadAllText(String path)
   at ConsoleApplication1.Program.LerConteudo(String nomeDoArquivo) in c:UsersIsraelDesktopConsoleApplication1ConsoleApplication1Program.cs:line 27
— End of stack trace from previous location where exception was thrown —
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at ConsoleApplication1.Program.LerConteudo(String nomeDoArquivo) in c:UsersIsraelDesktopConsoleApplication1ConsoleApplication1Program.cs:line 34
   at ConsoleApplication1.Program.Main(String[] args) in c:UsersIsraelDesktopConsoleApplication1ConsoleApplication1Program.cs:line 15

Anúncios

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s