Sind verschachtelte Try / Catch-Blöcke eine schlechte Idee?

80

Nehmen wir an, wir haben eine solche Struktur:

Try
  ' Outer try code, that can fail with more generic conditions, 
  ' that I know less about and might not be able to handle

  Try
    ' Inner try code, that can fail with more specific conditions,
    ' that I probably know more about, and are likely to handle appropriately
  Catch innerEx as Exception
    ' Handle the inner exception
  End Try

Catch outerEx as Exception
  ' Handle outer exception
End Try

Ich habe einige Meinungen gesehen, von denen solche Nistblöcke Tryabgeraten werden, aber ich konnte keine spezifischen Gründe finden.

Ist das ein schlechter Code? Wenn ja warum?

Goro
quelle
2
Ich bin mir nicht sicher, wie genau das Snippet wirklich ist. Aber es gibt keinen Teufel, den Sie wirklich kennen, wenn Sie Exception fangen. Es kann alles sein . Nutzen Sie die von VB.NET unterstützte When-Klausel.
Hans Passant

Antworten:

85

Unter bestimmten Umständen sind sie eine gute Idee, z. B. ein Versuch / Fang für die gesamte Methode und ein anderer innerhalb einer Schleife, wenn Sie die Ausnahme behandeln und den Rest einer Sammlung weiter verarbeiten möchten.

Wirklich der einzige Grund, dies zu tun, ist, wenn Sie das fehlerhafte Bit überspringen und weitermachen möchten, anstatt den Stapel abzuwickeln und den Kontext zu verlieren. Das Öffnen mehrerer Dateien in einem Editor ist ein Beispiel.

Ausnahmen sollten jedoch (wie der Name schon sagt) außergewöhnlich sein. Ein Programm sollte sie behandeln, aber versuchen, sie als Teil des normalen Ausführungsflusses zu vermeiden. Sie sind in den meisten Sprachen rechenintensiv (Python ist eine bemerkenswerte Ausnahme).

Eine andere Technik, die nützlich sein kann, ist das Abfangen bestimmter Ausnahmetypen ...

Try
    'Some code to read from a file

Catch ex as IOException
    'Handle file access issues (possibly silently depending on usage)
Catch ex as Exception
    ' Handle all other exceptions.
    ' If you've got a handler further up, just omit this Catch and let the 
    ' exception propagate
    Throw
End Try

Wir verwenden auch verschachtelte try / catches in unseren Fehlerbehandlungsroutinen ...

    Try
        Dim Message = String.Format("...", )
        Try
            'Log to database
        Catch ex As Exception
            'Do nothing
        End Try

        Try
            'Log to file
        Catch ex As Exception
            'Do nothing
        End Try
    Catch ex As Exception
        'Give up and go home
    End Try
Basic
quelle
7
Das Anmelden in einem Hintergrund-Thread ist ein Ort, an dem ich einen inneren Versuch / Fang verwenden werde. Ich möchte nicht, dass die Methode endet, weil sie nicht dokumentieren konnte, was sie tat.
Gooch
@ Gooch wahr, das mache ich auch, ich werde es meiner Antwort hinzufügen.
Basic
37

Ich glaube eigentlich nicht, dass irgendetwas an Verschachtelten Try/ CatchBlöcken von Natur aus falsch ist , außer dass sie schwierig zu navigieren sind und wahrscheinlich ein Zeichen dafür sind, dass Sie etwas umgestalten könnten ( zum Beispiel die innere Try/ Catchin ihre eigene Methode).

Aber ich möchte diesen Kommentar ansprechen:

' Outer try code, that can fail with more generic conditions, 
' that I know less about and might not be able to handle

Wenn Sie nicht wissen , wie Ausnahmen in einer bestimmten Situation zu handhaben , vertrauen Sie mir: nicht fangen sie. Es ist besser, Ihre App abstürzen zu lassen (ich meine, Sie wissen, protokollieren Sie sie; schlucken Sie sie einfach nicht), als etwas zu fangen, von dem Sie sich nicht erholen können, und dann Ihre App in einem beschädigten Zustand fröhlich auf ihrem Weg fortzusetzen . Das Verhalten wird von diesem Punkt an bestenfalls unvorhersehbar sein.

Dan Tao
quelle
Das ist wahr. Zum Zeitpunkt der äußeren Ausnahme möchte ich nicht weitermachen. Ich dachte mehr daran, die Anwendung ordnungsgemäß herunterfahren / neu starten zu können und den Benutzer nicht mit einem "hässlichen Absturz" zu schockieren
Goro
10
@Goro: In diesem Fall würde ich einen App-weiten Ausnahmebehandlungsmechanismus empfehlen (z. B. wenn dies WinForms ist, behandeln Sie das Application.UnhandledExceptionEreignis) anstatt pro Methode Try/ CatchBlöcke.
Dan Tao