Question

Comprendre la différence entre jeter ex et jeter , pourquoi le StackTrace d'origine conservé dans cet exemple:

    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);
    }

Mais pas dans celui-ci:

    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;
        }
    }

Le deuxième scénario est produit la même sortie que jeter ex serait?

Dans les deux cas, on attend de voir le numéro de ligne où y est initialisé.

Était-ce utile?

La solution

Je ne suis pas sûr que cette limitation est dans le langage C #, la CLI, ou la mise en œuvre Microsoft de ces derniers, mais votre deuxième exemple est un cas où un appel explicite à Exception.InternalPreserveStackTrace est nécessaire comme indiqué dans le poste suivant. Étant donné que cette méthode est internal, il doit généralement être appelé par la réflexion. Les problèmes de performance impliqués dans ce qui peut être presque complètement allégées en créant un Action<Exception> pour l'appel, comme indiqué à la fin de cette réponse.

Référence: exceptions et préserver Renvoi des la pile des appels trace complète

Modifier Après réexaminant ECMA-335 partition I §12.4.2 (gestion des exceptions) et la partition III §4.24 (rethrow), je crois maintenant que le comportement que vous voyez est une erreur sémantique le CLR (la mise en œuvre de Microsoft de la CLI). La seule référence spécifique au comportement est « A rethrow ne modifie pas la trace de la pile dans l'objet. » Dans le cas décrit ici, le rethrow est en fait modifier la trace de la pile, ce qui rend le PreserveStackTrace pirater une solution de contournement pour un défaut de savoir CLR.

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

PreserveStackTrace est ici une optimisation de celui de cette entrée de 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);
}

Autres conseils

Parce que dans le second exemple, vous rethrowing exception de même méthode. Dans la première sa lancée de différents thats méthode pourquoi. Dans une portée de la méthode, trace pile peut être seulement une.

Faites comme suit, la meilleure façon est d'envelopper toujours une exception dans une nouvelle exception, de sorte que vous verrez la profondeur d'exception.

  

"Si rethrow a été publié dans le   même méthode (exception trace de la pile   ne possède une information de numéro de ligne   par méthode, vous ne voyez jamais trace de la pile   que dans le procédé A, à la ligne n ° 2   exception a été levée et en même   Procédé A, il a été relancée à partir de la ligne   numéro 17, il ne contiendra que la dernière   numéro de ligne où exception   relancée "

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);        
}

Je suis surpris par tant de commentaires pas lire mon commentaire !! J'ai écrit dans le commentaire que vous devriez probablement déboiser en toute sécurité , il y a diverses raisons, si le code de niveau supérieur mange exception et vous ne savez pas qui et où exception a été levée, l'exploitation forestière vous aide à couper exception !!

Si vous n'avez pas besoin de se connecter, alors ne pas attraper l'exception.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top