Will code in a Finally statement fire if I return a value in a Try block?

C#.NetException HandlingTry Catch

C# Problem Overview


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
  }
}

C# Solutions


Solution 1 - C#

Simple answer: Yes.

Solution 2 - C#

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.

Solution 3 - C#

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

Solution 4 - C#

Quoting from MSDN

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

Solution 5 - C#

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.
}

Solution 6 - C#

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 https://stackoverflow.com/a/28483789/68231">here</a> for instance, but not anywhere in this particular question.)

Solution 7 - C#

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.

Solution 8 - C#

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.

Solution 9 - C#

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

https://stackoverflow.com/questions/31118912/finally-not-executed-within-threading-timer-in-combination-with-windows-service

Solution 10 - C#

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

Solution 11 - C#

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".

Solution 12 - C#

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJamesEggersView Question on Stackoverflow
Solution 1 - C#Andrew RollingsView Answer on Stackoverflow
Solution 2 - C#mmxView Answer on Stackoverflow
Solution 3 - C#Jon BView Answer on Stackoverflow
Solution 4 - C#PerpetualcoderView Answer on Stackoverflow
Solution 5 - C#marknView Answer on Stackoverflow
Solution 6 - C#Ken SmithView Answer on Stackoverflow
Solution 7 - C#Peter - Reinstate MonicaView Answer on Stackoverflow
Solution 8 - C#Jeffrey L WhitledgeView Answer on Stackoverflow
Solution 9 - C#StigView Answer on Stackoverflow
Solution 10 - C#Hakuna MatataView Answer on Stackoverflow
Solution 11 - C#Jonathan PerryView Answer on Stackoverflow
Solution 12 - C#Ashish SahuView Answer on Stackoverflow