Gute Praktiken beim Umgang mit Ausnahmen in C #

7

Ich habe in The Pragmatic Programmer gelesen, und in einigen anderen Artikeln (einschließlich einem von Joel Spolsky), dass Sie Ausnahmen nur in Ausnahmefällen werfen sollten. Andernfalls sollten Sie einen Fehler zurückgeben.

Manchmal ist es möglich (z. B. -1 , -0 oder positive number zurückzugeben), aber es gibt andere Fälle, in denen das nicht möglich ist. Ich meine, wenn Sie eine Klasse zurückgeben, können Sie immer null zurückgeben, aber ich denke, die Idee ist, etwas zurückzugeben, das den Anrufer warnt, was passiert ist.

Wenn ich immer null zurückgebe, glaube ich nicht, dass es sinnvoll ist zu sagen: Wenn diese Methode null zurückgibt, könnte das an A, B, C, D oder E liegen.

Also, wie genau kann das in C # implementiert werden?

Bearbeiten:
Stunden nachdem ich diese Frage gepostet habe, sah ich hier eine andere Frage, wo die Frage selbst war, ob der eingefügte Code eine gute Übung war oder nicht.

Ich sehe, dass das eine andere Art ist, zu tun, was ich hier gefragt habe. Hier ist der Link:

generische Eigenschaft Nachteile?

    
Oscar Mederos 06.05.2011, 21:52
quelle

7 Antworten

10

Wenn Sie Zahlen verwenden, widersprechen Sie direkt dem, was Microsoft mit Ausnahmen empfiehlt. Die beste Informationsquelle, die ich gefunden habe und die das ganze Thema entmystifiziert, ist Jeffrey Richters CLR über C # 3 . Auch das Framework-Leitfaden für .NET Framework ist eine Lektüre für sein Material zu Exceptions wert.

Um MSDN zu zitieren :

  

Fehlercodes werden nicht zurückgegeben. Ausnahmen sind das primäre Mittel zur Meldung von Fehlern in Frameworks.

Eine Lösung, die Sie übernehmen könnten, ist ein Parameter out , der das Ergebnis liefert. Ihre Methode gibt dann eine bool zurück, ähnlich wie eine Menge TryParse Methoden, die Sie im Framework treffen.

    
Chris S 06.05.2011, 21:57
quelle
11

Eine weitaus bessere Regel für das Auslösen von Ausnahmen ist:

Wirf eine Exception aus, wenn deine Methode das nicht kann, was ihr Name sagt.

Ein Nullwert kann verwendet werden, um anzuzeigen, dass Sie nach etwas gefragt haben, das nicht existiert. Es sollte für keine andere Fehlerbedingung zurückgegeben werden.

Die Regel "Exceptions nur in Ausnahmefällen auslösen" ist keine hilfreiche Waffle-IMO, da sie keine Benchmark gibt, um anzuzeigen, was außergewöhnlich ist und was nicht. Es ist wie "nur essen, das essbar ist."

    
jammycakes 06.05.2011 22:10
quelle
8

Ein zu berücksichtigendes Beispiel ist int.TryParse . Dies verwendet einen out -Parameter für den analysierten Wert und einen bool -Rückgabewert, um Erfolg oder Misserfolg anzuzeigen. Das bool könnte durch ein enum oder ein komplexeres Objekt ersetzt werden, wenn die Situation es verdient. (Zum Beispiel könnte die Datenvalidierung auf eine Art und Weise fehlschlagen, die eine Sammlung von Fehlern usw. wirklich rechtfertigen würde.)

Eine Alternative dazu mit .NET 4 ist Tuple ... so int.TryParse könnte gewesen sein:

%Vor%

Die nächste Möglichkeit besteht darin, dass ein Objekt das gesamte Ergebnis einkapselt, einschließlich des Fehlermodus, falls dies angebracht ist. Zum Beispiel können Sie ein Task<T> für sein Ergebnis, seinen Status und seine Ausnahme fragen, wenn es fehlgeschlagen ist.

All dies ist nur dann sinnvoll, wenn dies nicht wirklich ein Fehler ist. Es zeigt keinen Fehler an, nur etwas wie eine schlechte Benutzereingabe. Ich mag es nicht wie Fehlercodes zurückzugeben - Ausnahmen sind in .NET viel idiomatischer.

    
Jon Skeet 06.05.2011 21:57
quelle
1

Microsoft hat Best Practices für die Fehlerbehandlung in .NET dokumentiert.

Ссылка

Ich würde empfehlen, diesen Richtlinien zu folgen, da dies der Standard für .NET ist und Sie mit weitaus weniger Konflikten mit anderen .NET-Entwicklern konfrontiert werden.

(Beachten Sie, dass ich auf einen älteren Link gepostet habe, aber die Empfehlungen sind geblieben.)

Ich erkenne auch, dass verschiedene Plattformen davon abweichen, wie sie die richtige Fehlerbehandlung sehen. Dies könnte eine subjektive Frage sein, aber ich werde bei dem bleiben, was ich oben gesagt habe - wenn Sie in .NET entwickeln, folgen Sie den .NET-Richtlinien.

    
David 06.05.2011 21:58
quelle
1

Sie sollten vielleicht das Muster TryXXX mit ein paar einfachen Überladungen für den Client berücksichtigen.

%Vor%     
ChaosPandion 06.05.2011 21:58
quelle
1

Joel Spolsky hat Unrecht. Die Rückgabe des Status über Fehler- / Rückgabecodes bedeutet, dass Sie den Ergebnissen eines Methodenaufrufs nicht vertrauen können - der zurückgegebene Wert muss getestet und bearbeitet werden.

Dies bedeutet, dass jeder Methodenaufruf, der einen solchen Wert zurückgibt, mindestens einen Auswahlpunkt (oder mehr, abhängig von der Domäne des zurückgegebenen Werts) und somit mehr mögliche Ausführungspfade durch den Code einführt. Alle müssen getestet werden.

Wenn dieser Code unter der Annahme, dass der Vertrag von Method1 () und Method2 () entweder erfolgreich sein oder eine Ausnahme auslösen soll, hat er möglicherweise 1 durchfließen lassen.:

%Vor%

Wenn diese Methoden den Status über einen Return-Code anzeigen, wird es sehr schnell sehr unordentlich. Gib einfach einen binären Wert zurück:

%Vor%

Rückgabe von Statuscodes anstelle von Ausnahmen

  • erschwert das Testen
  • erschwert das Verständnis des Codes
  • wird fast sicher Bugs einführen, weil Entwickler nicht jeden möglichen Fall erfassen und testen werden (schließlich, wie oft haben Sie tatsächlich einen E / A-Fehler gesehen?).

Der Aufrufer sollte vor dem Aufruf der Methode prüfen, ob alles gut ist (z. B. Auf Dateiexistenz prüfen. Wenn die Datei nicht existiert, versuchen Sie nicht, sie zu öffnen).

Erzwinge die Verträge deiner Methode:

  • Vorbedingungen. Der Aufrufer garantiert, dass dies vor dem Aufruf der Methode zutrifft.
  • Postconditions. Aufrufer garantiert, dass diese nach dem Methodenaufruf erfüllt sind.
  • Invariante Bedingungen. Callee garantiert, dass diese immer wahr sind.

Wirf eine Ausnahme aus, wenn der Vertrag verletzt wird. Wenn etwas Unerwartetes passiert, wird eine Ausnahme ausgelöst.

Ihr Code sollte ein strenger Disziplinar sein.

    
Nicholas Carey 06.05.2011 22:18
quelle
0

Ich gebe solche Werte als null Referenzen oder negative Indexwerte nur zurück, wenn ich sicher bin, dass es kein Missverständnis geben wird, wenn der Code von einem anderen Entwickler verwendet wird. So etwas wie die LINQ-Funktion IEnumerable<T>.FirstOrDefault . IEnumerable<T>.First löst eine Ausnahme für leere Auflistungen aus, da erwartet wird, dass das erste Element zurückgegeben wird und die leere Auflistung ein Ausnahmefall ist

    
Marek 06.05.2011 22:01
quelle