258

I'm reviewing some code for a friend and say that he was using a return statement inside of a try-finally block. Does the code in the Finally section still fire even though the rest of the try block doesn't?

Example:

public bool someMethod()
{
  try
  {
    return true;
    throw new Exception("test"); // doesn't seem to get executed
  }
  finally
  {
    //code in question
  }
}
Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
JamesEggers
  • 12,885
  • 14
  • 59
  • 86
  • 1
    http://stackoverflow.com/q/449099 – amit jha Mar 31 '16 at 10:34
  • *Being handled* here means: caught. Even an empty catch block in your global handler is enough. Also, there are exceptions that cannot be handled: `StackOverflowException`, `ExecutionEngineException` are some of those. And since they cannot be handled, the `finally` won't run. – Abel Sep 02 '16 at 23:24
  • 8
    @Abel: You seem to be talking about a different situation. This question is about *returning* in a `try` block. Nothing about abrupt program aborts. – Jon Skeet Sep 22 '16 at 13:57
  • @JonSkeet, you mean that, if there is no exception, will `finally` always execute. Then yes. But if you `return` _after_ an exception, this is not guaranteed. That was my comment about indeed. – Abel Sep 22 '16 at 16:40
  • 6
    @Abel: I'm not sure what you mean by "return after an exception", but that doesn't seem to be what's being asked about here. Look at the code - the first statement of the `try` block is a `return` statement. (The second statement of that block is unreachable and will generate a warning.) – Jon Skeet Sep 22 '16 at 16:41
  • @JonSkeet, I see it now. My point was about `finally` not being guaranteed in all situations. – Abel Sep 22 '16 at 16:42
  • 5
    @Abel: Indeed, and if the question had been "Will code in a finally statement always execute in every situation" that would have been relevant. But that's not what was being asked. – Jon Skeet Sep 22 '16 at 16:44

12 Answers12

295

Simple answer: Yes.

Andrew Rollings
  • 14,340
  • 7
  • 51
  • 50
  • 10
    @Edi: Um, I don't see what background threads have to do with it. Basically, unless the whole process aborts, the `finally` block will execute. – Jon Skeet Sep 22 '16 at 13:57
  • 7
    The long answer is you won't necessarily get a finally block to run if something catastrophic has happened, such as a Stack Overflow, Out of Memory exception, a hard crash of some kind, or if someone unplugs your machine at just the right time. But for all intents and purposes, unless you're doing something very very wrong, the finally block will always fire. – Andrew Rollings Oct 10 '18 at 18:33
  • If code before try fails due to some reason I have noticed that finally still gets executed. In that case you can add a condition for in finally which satisfies criteria to execute finally only when code under executes successfully – kjosh Apr 29 '20 at 20:01
211

Normally, yes. The finally section is guaranteed to execute whatever happens including exceptions or return statement. An exception to this rule is an asynchronous exception happening on the thread (OutOfMemoryException, StackOverflowException).

To learn more about async exceptions and reliable code in that situations, read about constrained execution regions.

Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
169

Here's a little test:

class Class1
{
    [STAThread]
    static void Main(string[] args)
    {
        Console.WriteLine("before");
        Console.WriteLine(test());
        Console.WriteLine("after");
    }

    static string test()
    {
        try
        {
            return "return";
        }
        finally
        {
            Console.WriteLine("finally");
        }
    }
}

The result is:

before
finally
return
after
senshin
  • 10,022
  • 7
  • 46
  • 59
Jon B
  • 51,025
  • 31
  • 133
  • 161
  • 10
    @CodeBlend: It has to do with when the `WriteLine` for the result of the method call is actually performed. In this case the `return` call sets the methods result, finally writes to the console - before the method exits. Then the `WriteLine` in the Main method spits out the text from the return call. – NotMe Sep 04 '13 at 01:24
40

Quoting from MSDN

finally is used to guarantee a statement block of code executes regardless of how the preceding try block is exited.

Perpetualcoder
  • 13,501
  • 9
  • 64
  • 99
  • 3
    Well, in addition to Mehrdad's exceptional cases, finally also won't be called if you are debugging in a try block, and then stop debugging :). Nothing in life is guaranteed, it seems. – StuartLC Aug 22 '12 at 16:24
  • 1
    Not quite, quoting [from MSDN](https://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx): *However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up.*. – Abel Sep 02 '16 at 23:28
  • 2
    @Abel makes a crucial point here. Everybody can see how a finally block is not executed if e.g. the program is aborted via task manager. But this answer is, as it stands, plain wrong: `finally` in fact *guarantees* nothing even for perfectly ordinary programs (which happened to throw this exception). – Peter - Reinstate Monica Sep 22 '16 at 13:58
20

Generally yes, the finally will run.

For the following three scenarios, the finally will ALWAYS run:

  1. No exceptions occur
  2. Synchronous exceptions (exceptions that occur in normal program flow).
    This includes CLS compliant exceptions that derive from System.Exception and non-CLS compliant exceptions, which do not derive from System.Exception. Non-CLS compliant exceptions are automatically wrapped by the RuntimeWrappedException. C# cannot throw non-CLS complaint exceptions, but languages such as C++ can. C# could be calling into code written in a language that can throw non-CLS compliant exceptions.
  3. Asynchronous ThreadAbortException
    As of .NET 2.0, a ThreadAbortException will no longer prevent a finally from running. ThreadAbortException is now hoisted to before or after the finally. The finally will always run and will not be interrupted by a thread abort, so long as the try was actually entered before the thread abort occurred.

The following scenario, the finally will not run:

Asynchronous StackOverflowException.
As of .NET 2.0 a stack overflow will cause the process to terminate. The finally will not be run, unless a further constraint is applied to make the finally a CER (Constrained Execution Region). CERs should not be used in general user code. They should only be used where it is critical that clean-up code always run -- after all the process is shutting down on stack overflow anyway and all managed objects will therefore be cleaned-up by default. Thus, the only place a CER should be relevant is for resources that are allocated outside of the process, e.g., unmanaged handles.

Typically, unmanaged code is wrapped by some managed class before being consumed by user code. The managed wrapper class will typically make use of a SafeHandle to wrap the unmanaged handle. The SafeHandle implements a critical finalizer, and a Release method that is run in a CER to guarantee the execution of the clean-up code. For this reason, you should not see CERs littered through-out user code.

So the fact that the finally doesn't run on StackOverflowException should have no effect to user code, since the process will terminate anyway. If you have some edge case where you do need to clean-up some unmanaged resource, outside of a SafeHandle or CriticalFinalizerObject, then use a CER as follows; but please note, this is bad practice -- the unmanaged concept should be abstracted to a managed class(es) and appropriate SafeHandle(s) by design.

e.g.,

// No code can appear after this line, before the try
RuntimeHelpers.PrepareConstrainedRegions();
try
{ 
    // This is *NOT* a CER
}
finally
{
    // This is a CER; guaranteed to run, if the try was entered, 
    // even if a StackOverflowException occurs.
}
BIBD
  • 15,107
  • 25
  • 85
  • 137
markn
  • 279
  • 2
  • 3
  • Please note that even a CER won't run in the case of an SOE. At the time you wrote this up, the MSDN documentation on CER was wrong/incomplete. An SOE will trigger a `FailFast` internally. The only way I managed to catch those is by [customizing the CLR runtime hosting](http://www.codeproject.com/Articles/416471/CLR-Hosting-Customizing-the-CLR). Note that your point is still valid for some other asynchronous exceptions. – Abel Sep 02 '16 at 23:33
16

There's a very important exception to this which I haven't seen mentioned in any other answers, and which (after programming in C# for 18 years) I can't believe I didn't know.

If you throw or trigger an exception of any sort inside your catch block (not just weird StackOverflowExceptions and things of that ilk), and you don't have the entire try/catch/finally block inside another try/catch block, your finally block won't execute. This is easily demonstrated - and if I hadn't seen it myself, given how often I've read that it's only really weird, tiny corner-cases that can cause a finally block not to execute, I wouldn't have believed it.

static void Main(string[] args)
{
    Console.WriteLine("Beginning demo of how finally clause doesn't get executed");
    try
    {
        Console.WriteLine("Inside try but before exception.");
        throw new Exception("Exception #1");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Inside catch for the exception '{ex.Message}' (before throwing another exception).");
        throw;
    }
    finally
    {
        Console.WriteLine("This never gets executed, and that seems very, very wrong.");
    }

    Console.WriteLine("This never gets executed, but I wasn't expecting it to."); 
    Console.ReadLine();
}

I'm sure there's a reason for this, but it's bizarre that it's not more widely known. (It's noted here for instance, but not anywhere in this particular question.)

Ken Smith
  • 20,305
  • 15
  • 100
  • 147
8

I realize I'm late to the party but in the scenario (differing from the OP's example) where indeed an exception is thrown MSDN states (https://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx): "If the exception is not caught, execution of the finally block depends on whether the operating system chooses to trigger an exception unwind operation."

The finally block is only guaranteed to execute if some other function (such as Main) further up the call stack catches the exception. This detail is usually not a problem because all run time environments (CLR and OS) C# programs run on free most resources a process owns when it exits (file handles etc.). In some cases it may be crucial though: A database operation half underway which you want to commit resp. unwind; or some remote connection which may not be closed automatically by the OS and then blocks a server.

Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62
3

It will also not fire on uncaught exception and running in a thread hosted in a Windows Service

Finally is not executed when in a Thread running in a Windows Service

Stig
  • 1,974
  • 2
  • 23
  • 50
3

Yes. That is in fact that main point of a finally statement. Unless something catestrophic occurs (out of memory, computer unplugged, etc.) the finally statement should always be executed.

Jeffrey L Whitledge
  • 58,241
  • 9
  • 71
  • 99
  • 1
    I beg to disagree. Cf. my answer. A perfectly normal exception in the try block is sufficient to bypass the `finally` block if that exception is never caught. That caught *me* by surprise ;-). – Peter - Reinstate Monica Sep 22 '16 at 15:10
  • @PeterA.Schneider - That is interesting. Of course, the implications of that do not really change much. If nothing up the call stack is going to catch the exception, then that should mean (if I understand correctly) that the process is about to be terminated. So it is similar to the pulling-the-plug situation. I guess the takeaway from this is that you should always have a top-level or unhandled-exception catch. – Jeffrey L Whitledge Sep 26 '16 at 13:18
  • Exactly, that is what I understand as well. I found that surprising, too. True: The most common resources will be released automatically, in particular memory and opened files. But resources the OS doesn't know about -- open server or database connections as an example -- may stay open on the remote side because they have never been properly shut down; sockets keep lingering, etc. I guess it is prudent to have a top level exception handler, yes. – Peter - Reinstate Monica Sep 26 '16 at 14:28
2

finally wont run in case if you are exiting from the application using System.exit(0); as in

try
{
    System.out.println("try");
    System.exit(0);
}
finally
{
   System.out.println("finally");
}

the result would be just : try

  • 4
    You are answering in the wrong language I suppose, the question was about `c#`, but this seems to be `Java`. And besides that, in most cases `System.exit()` is a hint of a bad design :-) – z00l Oct 29 '14 at 22:54
0

99% of the scenarios it will be guaranteed that the code inside the finally block will run, however, think of this scenario: You have a thread that has a try->finally block (no catch) and you get an unhandled exception within that thread. In this case, the thread will exit and its finally block will not be executed (the application can continue to run in this case)

This scenario is pretty rare, but it's only to show that the answer is not ALWAYS "Yes", it's most of the time "Yes" and sometimes, in rare conditions, "No".

Jonathan Perry
  • 2,953
  • 2
  • 44
  • 51
0

The main purpose of finally block is to execute whatever is written inside it. It should not depend upon whatever happens in try or catch.However with System.Environment.Exit(1) the application will exit without moving to next line of code.

Ashish Sahu
  • 185
  • 1
  • 6