Ist es eine schlechte Praxis, innerhalb eines Try-Catch-Blocks zurückzukehren?

128

Also bin ich heute Morgen auf einen Code gestoßen, der so aussah:

try
{
    x = SomeThingDangerous();
    return x;
}
catch (Exception ex)
{
    throw new DangerousException(ex);
}
finally
{
    CleanUpDangerousStuff();
}

Jetzt wird dieser Code gut kompiliert und funktioniert so, wie er sollte, aber es fühlt sich einfach nicht richtig an, aus einem try-Block zurückzukehren, insbesondere wenn es endlich einen zugeordneten gibt.

Mein Hauptproblem ist, was passiert, wenn das endlich eine eigene Ausnahme auslöst? Sie haben eine zurückgegebene Variable, aber auch eine Ausnahme ... also bin ich interessiert zu wissen, was andere über die Rückkehr aus einem try-Block denken?

Lomaxx
quelle
13
Ein Vorteil dieses Stils ist, dass Sie nicht xaußerhalb des tryBlocks deklarieren müssen . Sie können die Erklärung in der Nähe der Verwendung aufbewahren.
David R Tribble

Antworten:

169

Nein, das ist keine schlechte Praxis. Wenn Sie dort platzieren, returnwo es Sinn macht, verbessern Sie die Lesbarkeit und Wartbarkeit und machen Ihren Code einfacher zu verstehen. Es sollte Sie nicht interessieren, da der finallyBlock ausgeführt wird, wenn eine returnAnweisung gefunden wird.

Mehrdad Afshari
quelle
19

Das wird endlich ausgeführt, egal was passiert, also spielt es keine Rolle.

Ed S.
quelle
9
Nein, es wird nicht nur ausgesteckt, es gibt einige Ausnahmen, die als asynchrone Ausnahmen bezeichnet werden, wie StackOverflowException, ThreadAbortException und OutOfMemoryException, die dazu führen können, dass der finally-Block nicht ausgeführt wird. Lesen Sie mehr über eingeschränkte Ausführungsbereiche für die Behandlung dieser Szenarien.
Mehrdad Afshari
14

Persönlich würde ich diese Art der Codierung vermeiden, da ich keine Lust habe, return-Anweisungen vor endgültigen Anweisungen zu sehen.

Mein Geist ist einfach und verarbeitet die Dinge eher linear. Wenn ich den Code für Trockenlauf durchlaufe, neige ich daher zu der Annahme, dass, sobald ich die return-Anweisung erreicht habe, alles Folgende keine Rolle spielt, was in diesem Fall offensichtlich ziemlich falsch ist (nicht, dass dies die return-Anweisung beeinflussen würde, aber was die Nebenwirkungen sein könnten).

Daher würde ich den Code so anordnen, dass die return-Anweisung immer nach den finally-Anweisungen erscheint.

Conrad
quelle
9

Dies kann Ihre Frage beantworten

Was passiert wirklich bei einem Versuch? {Return x; } endlich {x = null; } Aussage?

Wenn Sie diese Frage lesen, klingt es so, als könnten Sie in der finally-Anweisung eine andere try catch-Struktur haben, wenn Sie glauben, dass sie eine Ausnahme auslösen könnte. Der Compiler wird herausfinden, wann der Wert zurückgegeben werden soll.

Trotzdem ist es möglicherweise besser, Ihren Code trotzdem neu zu strukturieren, damit Sie später nicht verwirrt werden oder jemand anderes, der sich dessen möglicherweise ebenfalls nicht bewusst ist.

Spencer Ruport
quelle
hmmm sehr interessant. Das heißt, es ist sicher, aber heißt das, dass es vermieden werden sollte?
Lomaxx
3
Persönlich denke ich, dass dies die Lesbarkeit Ihres Codes etwas erschwert, und das allein würde ausreichen, um einen anderen Weg zur Strukturierung des Codes zu finden. Aber es ist wirklich nur eine persönliche Präferenz.
Spencer Ruport
3
Ich stimme eher Ihrer persönlichen Präferenz zu :)
lomaxx
Ich denke, dass die Rückkehr dort in Ordnung ist, wo sie ist. Die Methode gibt den Wert zurück, sofern keine Ausnahme ausgelöst wird. Es spielt keine Rolle, ob die Ausnahme im Code für die endgültige Bereinigung auftritt.
Lawrence Dol
Beachten Sie, dass die Einschränkung für die Rückkehr von finally in Java nicht vorhanden ist (aber ich denke, die Einschränkung ist gut - ein großes Lob an C #).
Lawrence Dol
5

Funktionell gibt es keinen Unterschied.

Es gibt jedoch einen Grund, dies nicht zu tun. Längere Methoden mit mehreren Austrittspunkten sind oft schwieriger zu lesen und zu analysieren. Dieser Einwand hat jedoch mehr mit return-Anweisungen zu tun als mit catch and finally blocks.

Ifeanyi Echeruo
quelle
Ich würde dies in Frage stellen, da Sie am Ende mehr Verschachtelung haben könnten, was es auch schwieriger macht, eine höhere zyklomatische Komplexität zu lesen
matt_lethargic
3

In Ihrem Beispiel ist jeder Weg gleichwertig. Ich wäre nicht einmal überrascht, wenn der Compiler denselben Code generieren würde. Wenn im finally-Block eine Ausnahme auftritt, treten dieselben Probleme auf, unabhängig davon, ob Sie die return-Anweisung in den Block oder außerhalb des Blocks einfügen.

Die eigentliche Frage ist stilistisch, welche am besten ist. Ich schreibe meine Methoden gerne so, dass es nur eine return-Anweisung gibt. Auf diese Weise ist es einfacher, den Ablauf der Methode zu sehen. Daraus folgt, dass ich auch die return-Anweisung als letzte setzen möchte, damit leicht zu erkennen ist, dass dies der Fall ist das Ende der Methode und das, was es zurückgibt.

Ich denke, da die return-Anweisung so ordentlich platziert ist wie die letzte Anweisung, ist es weniger wahrscheinlich, dass andere kommen und mehrere return-Anweisungen in andere Teile der Methode streuen.

Sei gewarnt
quelle