Ist für ein typisches Beispiel if...else
mit Ausnahmebehandlung das folgende Beispiel eine empfohlene Vorgehensweise, um Codeduplizierungen zu vermeiden?
try
{
if (GetDataFromServer())
{
return ProcessData();
}
else
{
throw new Exception();
}
catch(Exception ex)
{
return null;
}
anstatt...
try
{
if (GetDataFromServer())
{
return ProcessData();
}
else
{
return null;
}
}
catch(Exception ex)
{
return null;
}
Ich weiß, dass es einen leichten Leistungseinbruch gibt, aber ich frage mich, ob dies als akzeptable Praxis angesehen wird. Ich mache derzeit die zweite Methode - insbesondere in Fällen, in denen ich bestimmte Ausnahmen anders behandeln muss -, aber ich habe mich gefragt, ob die erste Methode für einfache Fälle geeignet ist.
c#
exception-handling
grovesNL
quelle
quelle
Antworten:
Die Verwendung der Ausnahmebehandlung für die Flusskontrolle wird von Microsoft nicht empfohlen.
Und ein runder Tisch zum Thema ist verfügbar.
Davon abgesehen unterstützt C # dies, und ich nehme an, es hängt von der aufgetretenen Bedingung ab, ob eine Ausnahme die am besten geeignete Antwort ist.
quelle
Der Leistungseinbruch ist höchstwahrscheinlich vernachlässigbar, wie in dieser Antwort erläutert .
Gehen wir also von der Idee aus, dass Leistung kein Problem ist. Sie werfen
System.Exception
, nur um die Ausführung in diecatch
Klausel zu verschieben . Einen zu werfenBadControlFlowThatShouldBeRewrittenException
wäre wahrscheinlich übertrieben.Lassen Sie uns das zusammenfassen. Wir haben:
GetDataFromServer
(Methodennamen sollten in C # PascalCase sein), die möglicherweise eine Ausnahme auslösen oder a zurückgeben kannbool
.true
, führen SieProcessData
.null
anderen Gründen .Es sieht so aus, als ob die Methode, mit der dieser Code geschrieben wird, einfach zu viele Dinge tut.
GetDataFromServer
Wenn Sie einbool
Aussehen wie einen Konstruktionsfehler zurückgeben, würde ich erwarten, dass diese Methode die DatenIEnumerable<SomeType>
zurückgibt, die sie vom Server erhält . Einige enthalten 0 oder mehr Elemente. Der Happy Path gibt n Elemente zurück, bei denen n> 0 ist , nicht so glücklich Der Pfad gibt 0 Elemente zurück und der unglückliche Pfad wird mit einer nicht behandelten Ausnahme in die Luft gesprengt, was auch immer das ist.Das ändert ziemlich viel daran, wie die Methode aussieht - auch hier ist es schwer zu sagen, ob dies sinnvoll ist, da der ursprüngliche Beitrag nur einen Exit-Punkt hat (und daher nicht kompiliert werden würde, da nicht alle Codepfade einen Wert zurückgeben ) Dies ist nur eine wilde Vermutung:
Hier würden Sie sich ansehen
ProcessData
und sehen, dass es das iteriertresult
, und zurückkehren,null
wenn es kein Element in der gibtIEnumerable
.Warum kehrt die Methode zurück
null
? Server war ausgefallen? Gibt es einen Fehler in der Abfrage? Die Verbindungszeichenfolge verwendet die falschen Anmeldeinformationen? Immer wenn SieGetDataFromServer
mit einer Ausnahme in die Luft jagen, die Sie nicht erwarten, schlucken Sie sie, schieben sie unter den Teppich und geben einennull
Wert zurück. Ich würde empfehlen, in diesem Fall bestimmte Ausnahmen abzufangen und alles andere zu protokollieren. Das Debuggen wird auf diese Weise viel einfacher.Mit einer allgemeinen
catch
Klausel, die die Ausnahme nicht erfasst, wird es ziemlich schwierig, etwas zu diagnostizieren. Ich würde dies stattdessen minimal tun:Jetzt können Sie zumindest brechen und prüfen,
e
ob etwas schief geht.TL; DR : Nein, Ausnahmen für die Flusskontrolle zu werfen und zu fangen ist keine gute Idee.
quelle
In Ihrer ersten Antwort gibt es einen Performance-Hit, der nicht vorhanden sein muss.
Wenn Sie die if-Anweisung verlassen, um in die Catch-Anweisung einzutreten, wenn Sie den Code nicht sozusagen umschalten müssen.
Wenn Sie
return null;
dies in der else-Anweisung tun möchten, nicht in einem catch, der abgefangen wird, nachdem er aus der else-Anweisung geworfen wurde.Gilt wahrscheinlich nicht für Ihren Real- Code, aber für den von Ihnen angegebenen generischen Code.
Standards sagen, dass Sie dies nicht tun sollten.
Standards sagen, dass Sie es so machen sollten (wieder basierend auf dem in OP angegebenen generischen Code)
und da Sie keine spezifischen Ausnahmen haben, die Sie fangen, sollten Sie hier nicht einmal einen Versuch machen.
Sie möchten Ausnahmen sehen, wenn sie auftreten, damit Sie das Problem beheben können, das die Ausnahme erstellt.
quelle
Warum nicht das viel einfachere:
Wenn ein Ausnahmebehandler vorhanden sein soll, sollte er sich in ProcessData () befinden.
quelle
ProcessData()
an die oberste Ebene weiterleiten wollen?ProcessData()
jetzt eine Ausnahme ausgelöst wird, wird diese nicht behandelt. Ich möchte, dass esreturn null
auf dieser EbeneProcessData()
eine Ausnahme auslöst, ohne sichProcessData()
selbst zu ändern .