119

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 would you put a statement in finally instead of just putting it after the whole try-catch block? Or in other words is there a difference between the following blocks of code:

try{ //a}
catch {//b}
finally {//c}


try{//a}
catch{//b}
//c

EDIT:
PEOPLE, I know what finally does, I have been using it for ages, but my question is in the above example putting //c in finally seems redundant, doesn't it?

6 Answers 6

155

The purpose of a finally block is to ensure that code gets run in three circumstances which would not very cleanly be handled using "catch" blocks alone:

  1. If code within the try block exits via fallthrough or return
  2. If code within a catch block either rethrows the caught exception, or--accidentally or intentionally--ends up throwing a new one.
  3. If the code within the try block encounters an exception for which the try has no catch.

One could copy the finally code before every return or throw, and wrap catch blocks within their own try/catch to allow for the possibility of an accidental exception occurring, but it's far easier to forgo all that and simply use a finally block.

BTW, one thing I wish language designers would include would be an exception argument to the finally block, to deal with the case where one needs to clean up after an exception but still wants it to percolate up the call stack (e.g. one could wrap the code for a constructor in such a construct, and Dispose the object under construction if the constructor was going to exit with an exception).

10
  • 36
    We tried, you catched, and we finally have an answer to this question! Commented Feb 25, 2016 at 14:23
  • 4
    I think the key here was that it also executes even if there is a return statement within the try/catch statement. Without this understanding, a finally clause would seem quite trivial knowing that a catch all would essentially allow the code after the try/catch block to execute regardless of an exception. Thanks a lot, @supercat!
    – Swivel
    Commented Oct 23, 2016 at 6:45
  • 1
    @Swivel: Both the return and the (typically re-) thrown exception within a catch cases are easier to handle with finally than without.
    – supercat
    Commented Oct 23, 2016 at 16:30
  • 2
    Sorry, but the third one is wrong. You can try a simple try and finally blocks in a Console application, Visual Studio 2019. Throw an exception in the try block, don't catch it, and the finally block will never be called...
    – S Itzik
    Commented Dec 1, 2020 at 8:02
  • 1
    Where is the change?I'm affraid #3 is still wrong. Please try it. Open Visual Studio 2019, Console application, .Net framework 4.7 and write inside the main, A try and a finally blocks without catch. Throw an exception inside the try block, and tell if the finally block is being executed.
    – S Itzik
    Commented Dec 1, 2020 at 20:13
10

To make it even easier to understand:

try{//a}
catch{//b}
//c

In above code, //c won't execute:

  • if you use "return" inside the try block. **
  • if you use "return" inside the catch block. **
  • if you raise any exception inside the catch block.
  • if your try block raises an exception that can't be caught by your catch block.

While in below code:

try{ //a}
catch {//b}
finally {//c}

//c will execute no matter what.

1
  • I like this answer much better than the accepted one. Clear and to the point: I can see exactly the reasons why/when finally is needed. Commented Feb 26 at 14:20
1

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:

  • A1 is the library code providing allocateResources() function
  • A2 is our code providing myFunction, consuming A1
  • A3 is some client code consuming myFunction 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:

  • if 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.
  • if 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.
  • before 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:

  1. The code is more readable: you look at the end and see WHAT the function returns. In multiple returns you must find all return occurences, inspect all the ifs, think about when the ifs are satisfied and only then you know what the function returns.
  2. The code can be optimized by compilers, see copy elision.

The reason for multiple returns is avoiding many nested ifs, but there are other techniques to solve it. Exceptions are exception in this rule.

0

Finally block is executed even if an exception thrown in the try block. Therefore, for instance if you opened a stream before, you may want to close that stream either an exception is thrown or not. Finally block is useful for such an issue.

2
  • 3
    But you could also close the stream after the try-catch without a finally block.
    – Gereon99
    Commented Jul 18, 2019 at 7:17
  • 5
    That doesn't answer OP's question. Commented Jul 18, 2019 at 23:12
0

Learn by example

let v = 0;
function f() {
    try {
        v = 1;
        return 2;
    } finally {
        v = 3;
        return 4;
    }
    v = 5;
    return 6;
}

const r = f();
console.log(r, v);

following prints "3, 4"

-3

Finally make sure your code is executed even if you get an exception.

The finally block is useful for cleaning up any resources allocated in the try block as well as running any code that must execute even if there is an exception

http://msdn.microsoft.com/en-us/library/zwc8s4fz(v=vs.80).aspx

5
  • 4
    but what is the difference between the two code blocks I mentioned? in both cases //c is executed, right?
    – Ali
    Commented Mar 13, 2012 at 16:20
  • @Ali - a finally block allows you to clean up any resources allocated and allow the excpetion to propogate back up the call stack if you are not handling the except locally.
    – Dampsquid
    Commented Mar 13, 2012 at 16:25
  • 7
    in the second version //c would NOT be executed, if the code in //a called 'return' to exit the function. finally makes sure //c is called, even if the function is exited early. ... schwehr.org/blog/archives/2012-03.html#e2012-03-01T13_11_15.txt Commented Mar 13, 2012 at 16:25
  • @Ali I don't believe you understood the answer (or, I suspect, finally). Your edited clarification does not change the question. Commented Mar 13, 2012 at 16:27
  • 7
    Does not answer the actual question. Commented May 24, 2016 at 7:52

Not the answer you're looking for? Browse other questions tagged or ask your own question.