Antworten:
Die Konstruktionen
try { ... }
catch () { ... } /* You can even omit the () here */
try { ... }
catch (Exception e) { ... }
sind insofern ähnlich, als beide jede im try
Block ausgelöste Ausnahme abfangen (und sollten vermieden werden , es sei denn, Sie verwenden dies einfach zum Protokollieren der Ausnahmen ). Schauen Sie sich nun diese an:
try { ... }
catch ()
{
/* ... */
throw;
}
try { ... }
catch (Exception e)
{
/* ... */
throw;
}
try { ... }
catch (Exception e)
{
/* ... */
throw e;
}
Der erste und der zweite Try-Catch-Block sind genau dasselbe, sie lösen einfach die aktuelle Ausnahme erneut aus, und diese Ausnahme behält ihre "Quelle" und die Stapelverfolgung bei.
Der dritte Try-Catch-Block ist anders. Wenn die Ausnahme ausgelöst wird, werden die Quelle und die Stapelverfolgung geändert, sodass der Eindruck entsteht, dass die Ausnahme von dieser Methode aus genau dieser Zeile throw e
in der Methode ausgelöst wurde, die diesen Try-Catch-Block enthält.
Welches solltest du verwenden? Es kommt wirklich auf jeden Fall an.
Angenommen, Sie haben eine Person
Klasse mit einer .Save()
Methode, die sie in einer Datenbank beibehält. Angenommen, Ihre Anwendung führt die Person.Save()
Methode irgendwo aus. Wenn sich Ihre Datenbank weigert, die Person zu speichern, .Save()
wird eine Ausnahme ausgelöst. Solltest du throw
oder throw e
in diesem Fall verwenden? Es hängt davon ab.
Was ich am liebsten mache:
try {
/* ... */
person.Save();
}
catch(DBException e) {
throw new InvalidPersonException(
"The person has an invalid state and could not be saved!",
e);
}
Dies sollte die DBException als "innere Ausnahme" der neueren Ausnahme setzen, die ausgelöst wird. Wenn Sie diese InvalidPersonException untersuchen, enthält der Stack-Trace Informationen zur Save-Methode (die möglicherweise ausreicht, um das Problem zu lösen). Sie haben jedoch weiterhin Zugriff auf die ursprüngliche Ausnahme, wenn Sie diese benötigen.
Als letzte Bemerkung, wenn Sie eine Ausnahme erwarten , sollten Sie diese eine bestimmte Ausnahme und nicht eine allgemeine Ausnahme wirklich abfangen Exception
, dh wenn Sie eine InvalidPersonException erwarten, sollten Sie Folgendes bevorzugen:
try { ... }
catch (InvalidPersonException e) { ... }
zu
try { ... }
catch (Exception e) { ... }
Viel Glück!
Der erste behält die Stapelverfolgung bei, während der zweite sie zurücksetzt. Dies bedeutet, dass bei Verwendung des zweiten Ansatzes die Stapelverfolgung der Ausnahme immer von dieser Methode ausgeht und Sie die ursprüngliche Ausnahmeverfolgung verlieren, was für jemanden, der Ausnahmeprotokolle liest, katastrophal sein kann, da er die ursprüngliche Ursache der Ausnahme nie herausfindet .
Der zweite Ansatz kann nützlich sein, wenn Sie dem Stack-Trace zusätzliche Informationen hinzufügen möchten, er wird jedoch folgendermaßen verwendet:
try
{
// do something
}
catch (Exception ex)
{
throw new Exception("Additional information...", ex);
}
Es gibt einen Blog- Beitrag , in dem die Unterschiede diskutiert werden.
throw
vs throw e
.
Du solltest benutzen
try { }
catch(Exception e)
{ throw }
Wenn Sie etwas mit der Ausnahme tun möchten, bevor Sie sie erneut auslösen (z. B. Protokollierung). Der einsame Wurf bewahrt die Stapelspur.
Der Unterschied zwischen einem parameterlosen Fang und einem catch(Exception e)
besteht darin, dass Sie einen Verweis auf die Ausnahme erhalten. Ab Framework Version 2 werden nicht verwaltete Ausnahmen in eine verwaltete Ausnahme eingeschlossen, sodass die parameterlose Ausnahme für nichts mehr nützlich ist.
Der Unterschied zwischen throw;
und throw e;
besteht darin, dass die erste zum erneuten Auslösen von Ausnahmen und die zweite zum Auslösen einer neu erstellten Ausnahme verwendet wird. Wenn Sie die zweite verwenden, um eine Ausnahme erneut auszulösen, wird sie wie eine neue Ausnahme behandelt und alle Stapelinformationen ersetzt, von denen sie ursprünglich ausgelöst wurden.
Sie sollten also keine der Alternativen in der Frage verwenden. Sie sollten den parameterlosen catch nicht verwenden und throw;
eine Ausnahme erneut auslösen.
In den meisten Fällen sollten Sie für alle Ausnahmen eine spezifischere Ausnahmeklasse als die Basisklasse verwenden. Sie sollten nur die Ausnahmen abfangen, die Sie erwarten.
try {
...
} catch (IOException e) {
...
throw;
}
Wenn Sie beim erneuten Auslösen der Ausnahme Informationen hinzufügen möchten, erstellen Sie eine neue Ausnahme mit der ursprünglichen Ausnahme als innere Ausnahme, um alle Informationen zu erhalten:
try {
...
} catch (IOException e) {
...
throw new ApplicationException("Some informative error message", e);
}