Ich bin nicht sicher, ob diese Einschränkung innerhalb der C# -Sprache, der CLI oder der Microsoft-Implementierung dieser ist, aber Ihr zweites Beispiel ist ein Fall, in dem ein expliziter Aufruf an Exception.InternalPreserveStackTrace
erforderlich ist, wie in dem folgenden Beitrag dokumentiert. Da diese Methode internal
ist, muss sie im Allgemeinen durch Reflexion aufgerufen werden. Die damit verbundenen Leistungsprobleme können durch Erstellen einer Action<Exception>
für den Anruf fast vollständig gemildert werden, wie am Ende dieser Antwort gezeigt.
Referenz: Rethrowing exceptions and preserving the full 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, das Sie sehen werden, ist ein semantischer Fehler in der CLR (Microsofts Implementierung der CLI). Der einzige spezifische Verweis auf das Verhalten ist "A rethrow
ändert die Stack-Ablaufverfolgung in dem Objekt nicht." In dem hier beschriebenen Fall ändert der erneute Durchlauf tatsächlich die Stapelverfolgung, wodurch der PreserveStackTrace
Hack ein Workaround für einen bekannten CLR-Fehler wird.
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);
}
Das ist großartig, danke für die Info. – Nariman