finally
ist ein syntaktischer Zucker, um das DRY-Prinzip im try-catch
Muster zuzulassen . Eine Ausnahme wird normalerweise ausgelöst, wenn der Bibliothekscode nicht genügend Informationen enthält, um einen bestimmten Status zu verarbeiten, und der Clientcode ihn lösen soll. Wenn Sie keine Trennung zwischen Bibliothek und Client-Code haben, können Sie alles mit if
statt behandeln try
.
Sehen wir uns eine Standardsituation ohne an finally
:
void myFunction() {
var r = allocateResources();
r.doSomething();
if(somethingBadHappens) {
freeResources(r);
throw new Exception(CODE42);
}
r.doSomethingMore();
freeResources(r);
}
Im obigen Snippet wiederholen Sie freeResources()
: Dies können mehrere Anweisungen sein, die Sie wiederholen müssen. Dieser Geruch und finally
Block ist die Lösung für sauberen Code:
void myFunction() {
var r = allocateResources();
try {
r.doSomething();
if(somethingBadHappens) throw new Exception(CODE42);
r.doSomethingMore();
}
finally {
freeResources(r);
}
happyFunction();
}
Lassen Sie uns drei Abstraktionsebenen realisieren:
- A1 ist der Bibliothekscode, der die
allocateResources()
Funktion bereitstellt
- A2 ist unser Code
myFunction
, der A1 verbraucht
- A3 ist ein Client-Code, der
myFunction
im Try-Catch-Block verbraucht wird :
function A3code() {
try {
myFunction();
doSomething();
}
catch(Exception e) {
// no hanging resources here
Console.WriteLine(e);
}
}
Nun wollen wir sehen, was passieren kann:
- Wenn
allocateResources()
wir A1 einwerfen, wissen wir nicht, wie wir in A2 damit umgehen sollen (A2-Code kann in einer konsolenfreien Umgebung ausgeführt werden), daher verschieben wir die Situation auf A3, ohne weiteren Code hinzuzufügen. Wenn hier eine Ausnahme ausgelöst wird, wird der finally-Block nicht ausgeführt , da an diesen finally
gebunden ist, try
der nicht eingegeben wurde.
- wenn
somethingBadHappens
in try - Block, die Stapel Abwicklungen bis A3 , wo die Situation gehandhabt wird , aber bevor es finally
wird Block ausgeführt , so dass wir es nicht brauchen zu wiederholen , wenn keine Ausnahmen passieren.
- bevor
finally
wir catch
Block hinzufügen und versuchen können, einige mögliche Ausnahmen von A1 zu lösen, die in aufrufenden r.doSomething
Methoden auftreten können. Normalerweise möchten wir Ausnahmen so schnell wie möglich behandeln, um den Client-Code (A3) für Client-Codierer komfortabler zu gestalten.
happyFunction()
wird nur ausgeführt, wenn nichts myFunction()
hineingeworfen wird (innerhalb oder außerhalb des try
Blocks).
Wie @supercat hervorhebt, wird der finally
Block auch ausgeführt, wenn der try
Block über return beendet wird. Ich schlage vor, Sie vermeiden diese schlechte Angewohnheit und haben nur eine Rückkehr in jeder Funktion (möglicherweise gibt es einige früh am Anfang der Funktionen). Die Gründe für Single-Return-Funktionen sind:
- Der Code ist besser lesbar: Sie sehen am Ende, WAS die Funktion zurückgibt. Bei mehreren Rückgaben müssen Sie alle Rückgabevorkommen finden, alle Wenns überprüfen, darüber nachdenken, wann die Wenns erfüllt sind, und erst dann wissen Sie, was die Funktion zurückgibt.
- Der Code kann von Compilern optimiert werden, siehe Kopierentscheidung .
Der Grund für mehrere Rückgaben besteht darin, viele verschachtelte Wenns zu vermeiden, aber es gibt andere Techniken, um dies zu lösen. Exception
s sind eine Ausnahme in dieser Regel.