finallyist ein syntaktischer Zucker, um das DRY-Prinzip im try-catchMuster 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 ifstatt 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 finallyBlock 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
myFunctionim 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 finallygebunden ist, tryder nicht eingegeben wurde.
- wenn
somethingBadHappensin try - Block, die Stapel Abwicklungen bis A3 , wo die Situation gehandhabt wird , aber bevor es finallywird Block ausgeführt , so dass wir es nicht brauchen zu wiederholen , wenn keine Ausnahmen passieren.
- bevor
finallywir catchBlock hinzufügen und versuchen können, einige mögliche Ausnahmen von A1 zu lösen, die in aufrufenden r.doSomethingMethoden 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 tryBlocks).
Wie @supercat hervorhebt, wird der finallyBlock auch ausgeführt, wenn der tryBlock ü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. Exceptions sind eine Ausnahme in dieser Regel.