Eigentlich wollte ich schon vor einem Monat einen kurzen Eintrag über die “throw” vs. “throw e” Problematik schreiben – Nun, endlich ist es soweit. Denn damals habe ich beim durchforsten von Code immer wieder “throw e;” innerhalb des catch-Blocks gesehen und mich etwas gewundert, das der Unterschied zwischen beiden “Rethrow”-Techniken offensichtlich nicht ganz durchgedrungen ist. Deshalb hier eine kleine Auffrischung.
Beides, also sowohl “throw;” als auch “throw e;” ist zum weiterwerfen einer Ausnahme gedacht. Doch während throw ohne Exception den Stackwalk beibehält, führt der throw mit Exception (also throw e;) ein Reset des Stackwalks durch. Dies ist vor allem beim Logging von Exceptions ein besonders unangenehmer Effekt, da dadurch der die Ausnahme verursachende Code schwieriger zu lokalisieren ist.
Grund dafür ist tatsächlich die unterschiedliche Übersetzung beider Instruktionen in den IL-Code. Dadurch wird einem auch klarer, dass “throw;” nicht nur die “bessere”, sondern auch die performantere Lösung ist.
Also: lieber “throw;” als “throw e;” – dann klappt’s auch mit der Log-Analyse besser.
Aber, es gibt natürlich auch die andere Seite der Medaille. Sprich: man kann z.B. durch bewußte Falschbehandlung der Ausnahme auch positive Effekte erzielen. Dies wird besonders bei sicherheitskritischen Informationen und Anwendungen interessant. Mike Stall vom CLR Debugging Team gibt ein schönes Beispiel, wie man “effizient” den Call-Stack verschleiern kann, ohne dabei die Exception ausser acht zu lassen:
Exception e = null;
try
{
SecuritySensitiveMethod();
}
catch(Exception e2)
{
e = e2;
}
if (e != null) throw MyNewException(e);
byMoilmsumsonMay 9th 2008Brilliant page!