Frage

Ich habe gerade eine Frage auf Try-Catch gesehen , die Menschen (einschließlich Jon Skeet) sagen leere catch-Blöcke sind eine wirklich schlechte Idee? Warum das? Gibt es keine Situation, in der eine leere Fang Entscheidung keine falsche Designs?

ich meine, zum Beispiel, manchmal hat man von irgendwo einige zusätzliche Informationen erhalten möchten (WebService, Datenbank), und Sie wirklich egal, wenn Sie diese Informationen bekommen oder nicht. Also versuchen Sie es zu bekommen, und wenn etwas passiert, das ist in Ordnung, ich werde nur eine „catch (Exception ignoriert) {}“ hinzufügen und das ist alles

War es hilfreich?

Lösung

In der Regel leer Try-Catch ist eine schlechte Idee, weil Sie stumm einen Fehlerzustand schlucken und dann die Ausführung fortgesetzt wird. Gelegentlich kann dies das Richtige zu tun, aber oft ist es ein Zeichen dafür, dass ein Entwickler eine Ausnahme sah, wusste nicht, was zu tun ist, und so einen leeren Haken zum Schweigen zu bringen, das Problem verwendet.

Es ist die Programmierung äquivalent schwarzes Klebeband über ein Motorwarnlicht zu stellen.

Ich glaube, dass, wie Sie mit Ausnahmen behandeln, auf welcher Ebene der Software hängt in dem Sie arbeiten: Ausnahmen im Regenwald .

Andere Tipps

Sie sind eine schlechte Idee im Allgemeinen , weil es eine wirklich seltene Erkrankung ist, wo ein Fehler (Ausnahmezustand, allgemeiner) ordnungsgemäß ohne Antwort auch immer erfüllt. Hinzu kommt, dass, sind leer catch Blöcke ein gemeinsames Werkzeug von Menschen, die die Ausnahme-Engine für Fehler verwenden Überprüfung, dass sie präventiv werden sollten tun.

sagen, dass es immer schlecht ist falsch ... das stimmt nur sehr wenig. Es kann Umstände geben, in denen entweder Sie kümmern sie nicht, dass es ein Fehler war oder dass das Vorhandensein des Fehlers anzeigt, irgendwie, dass man nicht sowieso nichts dagegen tun kann (zum Beispiel, wenn ein früheren Fehler in eine Textprotokolldatei zu schreiben und Sie IOException erhalten, was bedeutet, dass Sie nicht den neuen Fehler schreiben könnte sowieso).

Ich würde die Dinge nicht strecken, so weit zu sagen, dass die leeren catch-Blöcke verwendet einen schlechten Programmierer ist und nicht weiß, was er tut ...

Ich verwende leere catch-Blöcke, wenn nötig. Manchmal Programmierer der Bibliothek Ich bin raubend weiß nicht, was er tut und wirft Ausnahmen auch in Situationen, in denen niemand sie braucht.

Betrachten wir zum Beispiel einige HTTP-Server-Bibliothek, ich wurscht, wenn Server Ausnahme auslöst, weil Client getrennt hat und index.html konnte nicht gesendet werden.

Es gibt seltene Fälle, in denen es gerechtfertigt werden kann. In Python sehen Sie oft diese Art von Konstruktion:

try:
    result = foo()
except ValueError:
    result = None

So ist es in Ordnung sein könnte (je nach Anwendung) zu tun:

result = bar()
if result == None:
    try:
        result = foo()
    except ValueError:
        pass # Python pass is equivalent to { } in curly-brace languages
 # Now result == None if bar() returned None *and* foo() failed

In einem kürzlich erschienenen .NET-Projekt hatte ich Code schreiben Plugin DLLs aufzuzählen Klassen zu finden, die eine bestimmte Schnittstelle implementieren. Das entsprechende Stück Code (in VB.NET, sorry) ist:

    For Each dllFile As String In dllFiles
        Try
            ' Try to load the DLL as a .NET Assembly
            Dim dll As Assembly = Assembly.LoadFile(dllFile)
            ' Loop through the classes in the DLL
            For Each cls As Type In dll.GetExportedTypes()
                ' Does this class implement the interface?
                If interfaceType.IsAssignableFrom(cls) Then

                    ' ... more code here ...

                End If
            Next
        Catch ex As Exception
            ' Unable to load the Assembly or enumerate types -- just ignore
        End Try
    Next

Obwohl auch in diesem Fall würde ich zugeben, dass das Scheitern irgendwo Anmeldung wahrscheinlich eine Verbesserung wäre.

Leere catch-Blöcke sind in der Regel setzen in, weil der Codierer nicht wirklich wissen, was sie tun. Bei meiner Organisation ein leerer catch-Block muss einen Kommentar, warum mit der Ausnahme, nichts zu tun, ist eine gute Idee.

Auf einem verwandten beachten, die meisten Menschen wissen nicht, dass ein try {} Block entweder mit einem Haken gefolgt werden kann {} oder eine finally {}, nur eine erforderlich ist.

Ausnahmen sollten nur geworfen werden, wenn es wirklich eine Ausnahme ist - etwas außerhalb der Norm passiert. Ein leerer catch-Block im Grunde sagt, „etwas Schlimmes passiert, aber ich einfach nicht kümmern“. Dies ist eine schlechte Idee.

Wenn Sie nicht die Ausnahme behandeln wollen, lassen Sie es nach oben ausbreiten, bis es einen Code erreicht, der damit umgehen kann. Wenn nichts die Ausnahme behandeln kann, sollte es die Anwendung herunternehmen.

Ich denke, es ist okay, wenn Sie ein zu fangen insbesondere Ausnahmetyp, von denen Sie wissen es ist nur für einen insbesondere Grund angehoben werde, und Sie erwarten, dass die Ausnahme und wirklich braucht nicht, etwas dagegen zu tun.

Aber auch in diesem Fall eine Debug-Nachricht, um sein könnte.

Per Josh Bloch - Artikel 65: Ignorieren Sie nicht Ausnahmen von Effective Java :

  1. Ein leerer catch-Block Niederlagen den Zweck der Ausnahme
  2. Zumindest sollte der catch-Block einen Kommentar enthalten zu erklären, warum es empfiehlt sich, die Ausnahme zu ignorieren.

Ein leerer catch-Block sagt im Wesentlichen: „Ich will gar nicht wissen, welche Fehler geworfen werden, ich werde einfach zu ignorieren.“

Es ist ähnlich wie VB6 der On Error Resume Next, außer dass alles im try-Block, nachdem die Ausnahme ausgelöst wird, wird übersprungen.

Welche hilft nicht, wenn etwas bricht dann.

Dies geht Hand in Hand mit „Keine Ausnahmen verwenden, um Programmablauf zu steuern.“, Und: „Nur Ausnahmen für außergewöhnliche Umstände nutzen.“ Wenn diese fertig sind, dann sollten Ausnahmen nur auftreten, wenn es ein Problem gibt. Und wenn es ein Problem gibt, wollen Sie nicht still scheitern. In den seltenen Anomalien, wo es nicht notwendig ist, um das Problem zu umgehen Sie mindestens log die Ausnahme sollte nur für den Fall wird die Anomalie nicht mehr eine Anomalie. Das einzige, was schlimmer ist als andernfalls leise ausfällt.

Ich denke, ein völlig leerer catch-Block eine schlechte Idee ist, weil es keine Möglichkeit gibt, zu folgern, dass die Ausnahme ignoriert das beabsichtigte Verhalten des Codes war. Es ist nicht unbedingt schlecht, eine Ausnahme zu schlucken und falschen oder null oder einen anderen Wert in einigen Fällen zurück. Das .net Framework hat viele Methoden „versuchen“, die sich so verhalten. Als Faustregel gilt: Wenn Sie eine Ausnahme schlucken, fügen Sie einen Kommentar und eine Log-Anweisung, wenn die Anwendung Protokollierung unterstützt.

Weil, wenn eine Ausnahme ist geworfen werden Sie es nicht immer sehen - still versagt die schlechteste Option - Sie fehlerhaftes Verhalten bekommen und keine Ahnung zu suchen, wo es passiert. Mindestens eine Protokollnachricht dort setzen! Auch wenn es etwas, das ‚nie passieren kann‘!

Leere catch-Blöcke sind ein Anzeichen für einen Programmierer nicht wissen, was mit einer Ausnahme zu tun. Sie sind die Unterdrückung der Ausnahme von möglicherweise bis sprudeln und korrekt von einem anderen Try-Block behandelt werden. Versuchen Sie immer, und etwas zu tun, mit der Ausnahme, Sie zu kontrollieren.

Ich finde die nervigste mit leeren catch-Anweisungen, wenn ein anderer Programmierer es tut. Was ich meine ist, wenn Sie Debug-Code von jemand benötigen sonst keine leeren catch-Anweisungen macht ein solches Unternehmen schwieriger, dann müssen es sein. IMHO catch-Anweisungen sollten immer eine Art von Fehlermeldung - (. Alt nur im Debug-Modus), auch wenn der Fehler nicht behandelt wird es zumindest sollte es erkennen

Es ist wahrscheinlich nie das Richtige, weil Sie lautlos vorbei sind alle mögliche Ausnahme. Wenn es eine spezifische Ausnahme ist Sie erwarten, dann sollten Sie es testen, erneut auslösen, wenn es nicht Ihre Ausnahme ist.

try
{
    // Do some processing.
}
catch (FileNotFound fnf)
{
    HandleFileNotFound(fnf);
}
catch (Exception e)
{
    if (!IsGenericButExpected(e))
        throw;
}

public bool IsGenericButExpected(Exception exception)
{
    var expected = false;
    if (exception.Message == "some expected message")
    {
        // Handle gracefully ... ie. log or something.
        expected = true;
    }

    return expected;
}

Im Allgemeinen sollten Sie nur die Ausnahmen fangen Sie tatsächlich verarbeiten kann. Das heißt, so spezifisch wie möglich sein, wenn Ausnahmen zu kontrollieren. alle Ausnahmen Fangen ist selten eine gute Idee, und alle Ausnahmen zu ignorieren, ist fast immer eine sehr schlechte Idee.

Ich kann nur von wenigen Fällen denkt, wo ein leerer catch-Block einen sinnvollen Zweck hat. Wenn alles, was spezifische Ausnahme, fangen Sie wird „behandelt“ nur durch die Aktion erneut versucht, gäbe es keine Notwendigkeit, irgendetwas in dem catch-Block zu tun. Allerdings wäre es immer noch eine gute Idee, um die Tatsache zu melden Sie sich, dass die Ausnahme aufgetreten ist.

Ein weiteres Beispiel: CLR 2.0 verändert die Art und Weise nicht behandelte Ausnahmen auf dem Finalizerthread behandelt werden. Vor 2.0 wurde der Prozess erlaubt, dieses Szenario zu überleben. In der aktuellen CLR wird der Prozess im Fall einer nicht behandelt Ausnahme auf dem Finalizerthread beendet.

Beachten Sie, dass Sie nur einen Finalizer implementieren sollten, wenn Sie wirklich brauchen und selbst dann sollten Sie ein wenig wie möglich in der Finalizerthread zu tun. Aber wenn auch immer Arbeit Ihre Finalizerthread muss tun könnten eine Ausnahme auslösen, müssen Sie zwischen dem kleineren von zwei Übeln wählen. Haben Sie die Anwendung aufgrund der nicht behandelte Ausnahme heruntergefahren werden soll? Oder haben Sie in einem mehr oder weniger undefinierten Zustand fortfahren? Zumindest in der Theorie so kann dieser die kleinere von zwei Übeln in einigen Fällen sein. In diesem Fall würde der leere Fangblock den Prozess beendet wird von verhindern.

ich meine, zum Beispiel, manchmal will man von irgendwo einige zusätzliche Informationen erhalten (WebService, Datenbank), und Sie wirklich egal, wenn Sie diese Informationen bekommen oder nicht. Also versuchen Sie es zu bekommen, und wenn etwas passiert, das ist in Ordnung, ich werde nur eine „catch (Exception ignoriert) {}“ hinzufügen und das ist alles

Also, mit Ihrem Beispiel geht, es ist eine schlechte Idee, in diesem Fall, weil Sie fangen und zu ignorieren alle Ausnahmen. Wenn Sie wurden nur EInfoFromIrrelevantSourceNotAvailable fangen und ihn zu ignorieren, das wäre in Ordnung, aber du bist nicht. Sie ignorieren auch ENetworkIsDown, die nicht wichtig sind oder nicht. Sie ignorieren ENetworkCardHasMelted und EFPUHasDecidedThatOnePlusOneIsSeventeen, die mit ziemlicher Sicherheit wichtig sind.

Ein leerer catch-Block ist kein Problem, wenn es nur fängt eingerichtet ist (und ignoriert) Ausnahmen von bestimmten Arten, die Sie wissen, unwichtig zu sein. Die Situationen, in denen es eine gute Idee ist, zu unterdrücken und leise ignorieren alle Ausnahmen, ohne anzuhalten, sie zuerst zu prüfen, um zu sehen, ob sie irrelevant sind oder nicht erwartet / normal / sind äußerst selten.

Es gibt Situationen, in denen Sie sie verwenden könnten, aber sie sollten sehr selten sein. Situationen, in denen ich könnte man verwenden, schließen ein:

  • Ausnahme Protokollierung; je nach Kontext möchten Sie vielleicht eine nicht behandelte Ausnahme oder eine Nachricht geschrieben, statt.

  • Looping technische Situationen, wie Rendering oder Tonverarbeitung oder einen Listbox Rückruf, wo das Verhalten selbst das Problem demonstriert, wird eine Ausnahme wirft in der Quere kommt nur, und die Ausnahme der Anmeldung wird wahrscheinlich zur Folge hat nur in 1000 von "failed bis XXX" -Nachrichten.

  • Programme, die nicht scheitern, obwohl sie zumindest noch sein sollen, etwas anzumelden.

Für die meisten WinForms-Anwendungen, ich habe festgestellt, dass es eine einzige try-Anweisung für jede Benutzereingabe haben genügt. Ich verwende die folgenden Methoden: (Alertbox ist nur ein kurzer MessageBox.Show Wrapper)

  public static bool TryAction(Action pAction)
  {
     try { pAction(); return true; }
     catch (Exception exception)
     {
        LogException(exception);
        return false;
     }
  }

  public static bool TryActionQuietly(Action pAction)
  {
     try { pAction(); return true; }
     catch(Exception exception)
     {
        LogExceptionQuietly(exception);
        return false;
     }
  }

  public static void LogException(Exception pException)
  {
     try
     {
        AlertBox(pException, true);
        LogExceptionQuietly(pException);
     }
     catch { }
  }

  public static void LogExceptionQuietly(Exception pException)
  {
     try { Debug.WriteLine("Exception: {0}", pException.Message); } catch { }
  }

Dann kann jeder Event-Handler so etwas wie:

  private void mCloseToolStripMenuItem_Click(object pSender, EventArgs pEventArgs)
  {
     EditorDefines.TryAction(Dispose);
  }

oder

  private void MainForm_Paint(object pSender, PaintEventArgs pEventArgs)
  {
     EditorDefines.TryActionQuietly(() => Render(pEventArgs));
  }

Theoretisch könnte man TryActionSilently haben, die Anrufe für die Darstellung besser sein könnte, so dass eine Ausnahme eine endlose Menge von Nachrichten nicht erzeugen.

Sie sollten niemals einen leeren catch-Block haben. Es ist wie versteckt einen Fehler, den Sie kennen. Zumindest sollten Sie eine Ausnahme in eine Protokolldatei schreiben, später zu überprüfen, wenn Sie für die Zeit gedrückt werden.

Wenn Sie nicht wissen, was in catch-Block zu tun, können Sie einfach diese Ausnahme einzuloggen, aber es nicht leer lassen.

        try
        {
            string a = "125";
            int b = int.Parse(a);
        }
        catch (Exception ex)
        {
            Log.LogError(ex);
        }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top