I have used try-catch/except-finally variants in many languages for years, today someone asked me what is the point of finally and I couldn\'t answer.
Basically why wo
finally
is a syntactic sugar to allow DRY principle in try-catch
pattern. Exception is usually thrown if the library code has not enough information to handle some state and wants the client code to solve it. If you don't have library-client code separation, you can handle everything by if
instead of try
.
Let's see a standard situation without finally
:
void myFunction() {
var r = allocateResources();
r.doSomething();
if(somethingBadHappens) {
freeResources(r);
throw new Exception(CODE42);
}
r.doSomethingMore();
freeResources(r);
}
In the snippet above, you repeat freeResources()
: this can be multiple statements which you need to repeat. This smells and finally
block is the solution for clean code:
void myFunction() {
var r = allocateResources();
try {
r.doSomething();
if(somethingBadHappens) throw new Exception(CODE42);
r.doSomethingMore();
}
finally {
freeResources(r);
}
happyFunction();
}
Let's realize three levels of abstraction:
allocateResources()
functionmyFunction
, consuming A1myFunction
in try-catch block:function A3code() {
try {
myFunction();
doSomething();
}
catch(Exception e) {
// no hanging resources here
Console.WriteLine(e);
}
}
Now let's see what can happen:
allocateResources()
throws in A1, we don't know how to handle it in A2 (A2 code can be run in Console-free environment), so we delagate the situation to A3 without adding any further code. If Exception is thrown here, the finally block is not executed, since finally
is bound to try
which was not entered.somethingBadHappens
in try block, the stack unwinds to A3 where the situation is handled BUT before it finally
block is executed, so we don't need to repeat it if no exceptions happen.finally
we can add catch
block and try to resolve some potential exceptions from A1 which may appear in calling r.doSomething
methods. Usually we want to handle exceptions as soon as possible to make the client code (A3) more comfortable for client coders.happyFunction()
is executed only if nothing throws in myFunction()
(inside or outside of try
block).As @supercat points out, the finally
block is executed also if try
block exits via return. I suggest you avoid this bad habit and have only one return in every function (maybe some early exists at the very beginning of functions). The reasons for single-return functions are:
The reason for multiple returns is avoiding many nested ifs, but there are other techniques to solve it. Exception
s are exception in this rule.