Mehrfachversuch oder einer?

75

Normalerweise würde ich das tun:

try
{
    code

    code that might throw an anticipated exception you want to handle

    code

    code that might throw an anticipated exception you want to handle

    code
}
catch 
{

}

Gibt es irgendwelche Vorteile, wenn man es so macht?

code

try
{
    code that might throw an anticipated exception you want to handle
}
catch
{
}

code

try
{
    code that might throw an anticipated exception you want to handle
}
catch
{
}

code

Aktualisieren:

Ich habe diese Frage ursprünglich mit Verweis auf C # gestellt, aber wie A. Levy kommentierte, kann sie für jede Ausnahmebehandlungssprache gelten, sodass die Tags dies widerspiegeln.

Steve
quelle
7
Möchten Sie, dass die Verarbeitung gestoppt wird, sobald der erste Fehler auftritt (erstes Beispiel), oder kann sie fortgesetzt werden, auch wenn ein Teil der Verarbeitung fehlschlägt (der andere)?
David Pratte
2
@DLP - Ich möchte, dass die Verarbeitung beendet wird. Ich sehe, dass jemand es nach Ihnen erwähnt hat. Das ist ein guter Punkt.
Steve
4
Obwohl Sie dies mit C # und .net markiert haben, denke ich, dass es wirklich sprachunabhängig ist. Diese Frage gilt für alle Sprachen mit Ausnahmen wie Java, C ++, JavaScript, OCaml, F #, Python, Clojure usw. Sie gilt auch für das Bedingungs- / Neustartsystem in Common Lisp und verschiedenen anderen Lisps. Also würde ich Sie bitten, diese Sprache agnostisch zu machen ... Ihr Anruf jedoch.
A. Levy

Antworten:

87

Es hängt davon ab, ob. Wenn Sie eine spezielle Behandlung für bestimmte Fehler bereitstellen möchten, verwenden Sie mehrere Fangblöcke:

try
{ 
    // code that throws an exception
    // this line won't execute
}
catch (StackOverflowException ex)
{
    // special handling for StackOverflowException 
}
catch (Exception ex)
{
   // all others
}

Wenn jedoch eine Ausnahme behandelt und die Ausführung fortgesetzt werden soll, platzieren Sie den Code in separaten Try-Catch-Blöcken:

try
{ 
    // code that throws an exception

}
catch (Exception ex)
{
   // handle
}

try
{ 
    // this code will execute unless the previous catch block 
    // throws an exception (re-throw or new exception) 
}
catch (Exception ex)
{
   // handle
}
Jamie Ide
quelle
4
+1, Im ersten Beispiel hervorgehoben, stellen Sie sicher, dass der Handler für allgemeine Ausnahmen der letzte in der Deklaration ist, damit Sie zuerst bestimmte Punkte behandeln und alles andere außerhalb Ihrer Kontrolle generisch behandelt wird.
Leeroya
Wie hier angegeben: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… , Die Verwendung von bedingten Fängen ist nicht Standard und befindet sich nicht auf einer Standardspur. Verwenden Sie es nicht auf Produktionsstandorten mit Blick auf das Web: Es funktioniert nicht für jeden Benutzer. Es kann auch große Inkompatibilitäten zwischen Implementierungen geben, und das Verhalten kann sich in Zukunft ändern.
JLavoie
16

Wenn ich die zweite wählen könnte, würde ich dies wahrscheinlich in zwei Funktionen aufteilen.

Darin Dimitrov
quelle
5
+1: Ich stimme vollkommen zu, obwohl ich dies wahrscheinlich als "Wenn ich die zweite wählen könnte, würde ich ..." schreiben würde, da ich denke, dass dies das Richtige ist, wann immer es möglich ist ...
Reed Copsey
11

Verwenden Sie auch nicht einfach mehrere Catch-Blöcke für bestimmte Ausnahmen (es sei denn, der Block enthält nur eine Tonne Code und nur ein paar Zeilen können eine Ausnahme auslösen. In diesem Fall würde ich die zweite Methode verwenden).

Ed S.
quelle
9

Du denkst falsch darüber nach. Was müssen Sie in Ihren Fangblöcken tun? Wenn Sie eine der möglichen Ausnahmen wiederherstellen würden , indem Sie denselben Code ausführen, unabhängig davon, welche Operation die Ausnahme ausgelöst hat, verwenden Sie einen catch-Block. Wenn Sie je nach geworfener Operation unterschiedliche Bereinigungsvorgänge ausführen müssen, verwenden Sie mehrere Fangblöcke.

Wenn Sie try / finally oder das RAII- Muster anstelle von try / catch verwenden können, sollten Sie dies auch tun.

zwol
quelle
4

Die zweite Methode ist meiner Meinung nach besser, weil Sie damit Fehler genauer erfassen können.

Es ist auch schlecht, den gesamten Code in einen großen Try / Catch-Block zu packen, wenn Ihre App ein Problem hat und abstürzt. Da Sie jedoch eine große generische Ausführung abgefangen haben, ist die Wahrscheinlichkeit geringer, dass Sie tatsächlich richtig damit umgehen können. Sie sollten bestimmte Teile in try catch haben, z. B. wenn Sie eine Datei lesen oder Benutzereingaben vornehmen. Auf diese Weise können Sie mit dieser Ausnahme besser umgehen

EKS
quelle
2

Ich bevorzuge die zweite Methode - sie erleichtert das Debuggen, die Fehlerbehandlung genauer und fließt auch gut in Ihre Unit-Tests ein.

Andy
quelle
2

Ich würde mich für die zweite Option entscheiden, aber wenn ich dieses Codemuster sehe, ist mein erstes Gefühl, darüber nachzudenken, es in mehrere Funktionen / Methoden aufzuteilen. Ob dies zu tun ist, hängt natürlich davon ab, was der Code tut;)

Barrylloyd
quelle
2

Dies hängt von der Art der Fehler ab, die in Ihrem Code auftreten.

  1. Wenn die Behandlung dieser Fehler, die Sie ausführen werden, dieselbe ist, versuchen Sie es mit einem einzigen Versuch ... fangen Sie für diese Codegruppe. Sonst wird es zu langweilig.

  2. Wenn die Fehler eine andere Behandlung erforderten, trennen Sie sie, weil Sie müssen.

Wenden Sie nicht für alle Fälle eine einzige Methode an. Das meiste Programmieren ist kontextspezifisch :)

Sie müssen ein Gleichgewicht zwischen "GUT / KOMPLEX" und "SCHLECHT / EINFACH" erreichen. Je mehr Sie codieren, desto weniger stecken Sie in einem solchen Dilemma fest :)

Viel Spaß beim Programmieren!

ttchong
quelle
2
Im Allgemeinen ist es eine schlechte Form, einen ganzen Satz in Feststelltaste zu schreiben. Aber am Ende ist das kontextspezifisch
Joe Phillips
1

Zweite Methode. Wenn Sie den Code, der möglicherweise eine Ausnahme auslöst, von anderem Code trennen, bleibt der Abschnitt kleiner und einfacher zu verwalten, anstatt den gesamten Code zu verpacken, auch den, der keine Ausnahmen auslöst.

Mark Schultheiss
quelle
1

Es gibt Zeiten, in denen wir dem Benutzer einen bestimmten Fehler anzeigen möchten.

try{
   try{
      ... send message
   }
   catch(exception e){
    ...log error
    ...rethrow  send related error/show custom error
   }
   try{
       ...try to receive response
   }
   catch(exception e){
       ...show receive related error
   }
   //finally close the connection
   }finally{
        ...close connection
   }
Ashburn RK
quelle
-1

2. Weg, aber idealerweise Code Guards verwenden - Try / Catch kann teuer sein, wenn Sie eine Ausnahme abfangen.

CarneyCode
quelle
2
Try / Catch in C # ist wirklich nicht sehr kostspielig, es sei denn, Sie fangen tatsächlich etwas ...
Reed Copsey
2
PS: Mir ist klar, dass diese Antwort 7 Jahre alt ist, aber ich möchte sie in den Kontext von 2017 stellen. Der Performance-Hit von Try / Catch ist stark überbewertet und Leistungssteigerungen der Imagination sind NIE ein guter Grund für besseren, zuverlässigeren Code, insbesondere Wenn Sie feststellen, dass .NET der beste Computer war, den Sie kaufen konnten, war ein Pentium 4 mit 1-2 GB RAM. Heute haben wir 4 Kerne mit Hyper-Threading, das ist mehr als das 8-fache der Geschwindigkeit, und 8-16 GB RAM sind die Norm. Darüber hinaus ist kompilierter .NET-Code auch auf derselben Hardware schneller als vor 15 Jahren. Try / Catch langsam zu nennen ist ein Mythos und muss aufhören.
TravisO