Frage

Das Verständnis der Unterschied zwischen throw ex und throw , warum die ursprüngliche Stacktrace in diesem Beispiel erhalten wird:

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

Aber nicht in dieser:

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

Das zweite Szenario erzeugt die gleiche Ausgabe wie throw ex würde?

In beiden Fällen erwartet man die Zeilennummer zu sehen, wo y initialisiert.

War es hilfreich?

Lösung

Ich bin mir nicht sicher, ob diese Einschränkung in der Sprache C # ist, die CLI oder die Microsoft-Implementierung von diesen, aber Ihr zweites Beispiel ist ein Fall, in dem ein expliziten Aufruf Exception.InternalPreserveStackTrace erforderlich ist, wie im folgenden Beitrag dokumentiert. Da dieses Verfahren internal wird, hat es in der Regel durch Reflexion aufgerufen werden. Die Performance-Probleme in diesem beteiligt fast vollständig durch die Schaffung eines Action<Exception> für den Anruf gelindert werden, wie am Ende dieser Antwort gezeigt.

Referenz: Erneutes Auslösen von Ausnahmen und die Erhaltung des vollen Call-Stack-Trace

Edit: Nach Neuüberprüfen ECMA-335 Partition I §12.4.2 (Exception Handling) und Partition III §4.24 (rethrow), glaube ich jetzt, dass das Verhalten Sie sehen ein semantischer Fehler in die CLR (Microsofts Implementierung des CLI). Der einzige spezifische Bezug auf das Verhalten ist „A rethrow nicht den Stack-Trace in dem Objekt nicht ändert.“ In der hier beschriebenen Fall, die rethrow in der Tat ist die Stack-Trace zu verändern, so dass die PreserveStackTrace für einen Know CLR Fehler eine Abhilfe hacken.

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

PreserveStackTrace hier ist eine Optimierung des einer aus diesem Blog-Eintrag:

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

Andere Tipps

Da im zweiten Beispiel, Sie Erneutes Auslösen Ausnahme von derselben Methode. warum in dem ersten sein aus verschiedenen Verfahren, das ist geworfen. In einem Verfahren Umfang, Stack-Trace kann nur einen geben.

Do, wie folgend, der beste Weg ist, immer eine Ausnahme in einer neuen Ausnahme zu wickeln, so dass Sie Ausnahme Tiefe sehen.

  

"Wenn rethrow wurde in in der ausgestellt   gleiche Methode (Ausnahmestapelüberwachung   hat nur eine Zeilennummer   pro-Methode finden Sie nie Stack-Trace   daß in Methode A, bei der Zeilennummer 2   Ausnahme geworfen wurde und dann in gleichen   Verfahren A, wurde es von der Leitung erneut ausgelöst   17 Nummer, es wird nur enthalten letztes   Zeilennummer, von wo Ausnahme war   erneut ausgelöst "

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

Ich bin von so vielen Kommentaren überrascht nicht mein Kommentar lesen !! Ich schrieb in Kommentar, dass Sie wahrscheinlich diese sicher einzuloggen sollte , gibt es verschiedene Gründe, wenn die Top-Level-Code eats up Ausnahme und Sie nicht wissen, was und wo Ausnahme ausgelöst wurde, Protokollierung Sie schneiden Ausnahme hilft !! !

Wenn Sie nicht anmelden müssen, dann nicht die Ausnahme abfangen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top