Pergunta

Entender a diferença entre jogue ex e lançar, por que o Stacktrace original é preservado neste exemplo:

    static void Main(string[] args)
    {
        try
        {
            LongFaultyMethod();
        }
        catch (System.Exception ex)
        {
            Console.WriteLine(ex.StackTrace);
        }
    }

    static void LongFaultyMethod()
    {
        try
        {
            int x = 20;
            SomethingThatThrowsException(x);
        }
        catch (Exception)
        {
            throw;
        }
    }

    static void SomethingThatThrowsException(int x)
    {
        int y = x / (x - x);
    }

Mas não neste:

    static void Main(string[] args)
    {
        try
        {
            LongFaultyMethod();
        }
        catch (System.Exception ex)
        {
            Console.WriteLine(ex.StackTrace);
        }
    }

    static void LongFaultyMethod()
    {
        try
        {
            int x = 20;
            int y = x / (x - 20);
        }
        catch (Exception)
        {
            throw;
        }
    }

O segundo cenário está produzindo a mesma saída que jogue ex gostaria?

Nos dois casos, espera -se ver o número da linha em que Y é inicializado.

Foi útil?

Solução

Não tenho certeza se essa limitação está dentro da linguagem C#, a CLI ou a implementação da Microsoft, mas seu segundo exemplo é um caso em que uma chamada explícita para Exception.InternalPreserveStackTrace é necessário conforme documentado na postagem a seguir. Uma vez que este método é internal, geralmente deve ser chamado através da reflexão. As questões de desempenho envolvidas nisso podem ser quase completamente aliviadas, criando um Action<Exception> para a chamada, como mostrado no final desta resposta.

Referência: Retilando exceções e preservação do rastreamento completo da pilha de chamadas

Editar: Depois de reexaminar a partição da ECMA-335 I §12.4.2 (manuseio de exceção) e Partição III §4.24 (Rethrow), agora acredito que o comportamento que você está vendo é um erro semântico no CLR (implementação da Microsoft da CLI). A única referência específica ao comportamento é "a rethrow não muda o rastreamento da pilha no objeto. "No caso descrito aqui, o Rethrow está de fato alterando o rastreamento da pilha, fazendo o PreserveStackTrace Hackear uma solução alternativa para uma falha de Clr Know.

static void LongFaultyMethod() 
{ 
    try 
    { 
        int x = 20; 
        int y = x / (x - 20); 
    } 
    catch (Exception ex) 
    { 
        PreserveStackTrace(ex); // <-- add this line
        throw; 
    } 
} 

PreserveStackTrace Aqui está uma otimização da entrada da entrada do blog:

private static readonly Action<Exception> _internalPreserveStackTrace =
    (Action<Exception>)Delegate.CreateDelegate(
        typeof(Action<Exception>),
        typeof(Exception).GetMethod(
            "InternalPreserveStackTrace",
            BindingFlags.Instance | BindingFlags.NonPublic));

public static void PreserveStackTrace(Exception e)
{
    _internalPreserveStackTrace(e);
}

Outras dicas

Porque no segundo exemplo, você está retirando a exceção do mesmo método. Primeiro, é jogado de um método diferente, é por que. Em um escopo de método, o Stack Trace pode ser apenas um.

Faça o seguinte, a melhor maneira é sempre envolver uma exceção dentro de uma nova exceção, para que você verá a profundidade da exceção.

"Se Rethrow foi emitido no mesmo método (o rastreamento da pilha de exceção possui apenas uma informação de número de linha por método, você nunca vê rastreamento de pilha que no método A, na linha 2, a exceção foi lançada e depois no mesmo método A, foi RETHROWN da linha número 17, ele conterá apenas o número da última linha de onde a exceção era Rethrown "

try        
{            
   int x = 20;            
   int y = x / (x - 20);        
}        
catch (Exception ex)        
{            
   // do something here.. like log or something
   throw new Exception("Internal Exception", ex);        
}

Estou surpreso com tantos comentários que não leem meu comentário !! Eu escrevi em comentário que você provavelmente deveria registrar isso com segurança, existem várias razões, se o código de nível superior consumir uma exceção e você não sabe qual e onde a exceção foi lançada, o registro ajudará você a cruzar a exceção !!!

Se você não precisar registrar, não pegue a exceção.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top