85

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

Consider the following code C# code. Does the "finally" block execute?

public void DoesThisExecute() {
   string ext = "xlsx";
   string message = string.Empty;
   try {
      switch (ext) {
         case "xls": message = "Great choice!"; break;
         case "csv": message = "Better choice!"; break;
         case "exe": message = "Do not try to break me!"; break;
         default:
            message = "You will not win!";
            return;
      }
   }
   catch (Exception) {
      // Handle an exception.
   }
   finally {
      MessageBox.Show(message);
   }
}

Ha, after I got done writing this, I realized I could have done tested this myself in Visual Studio. However, please feel free to answer!

Community
  • 1
  • 1
Ryan Rodemoyer
  • 5,548
  • 12
  • 44
  • 54

11 Answers11

93

No it does not. It will always execute provided the application is still running (except during a FastFail exception, MSDN link, like others noted). It will execute when it exits the try/catch portion of the block.

It will NOT execute if the application crashes: gets killed through a kill process command etc. This is highly important, because if you write code that absolutely expects it to run, like manually doing a roll back, and if not other wise it will automatically commit, you can run into a scenario the application aborts before that happens. Honestly, this is an outside scenario, but it is important to take note of in those situations.

kemiller2002
  • 113,795
  • 27
  • 197
  • 251
  • 4
    This also includes some Exceptions (the three .net Exceptions that can't be caught), Application.FailFast or a Power Outage (http://thedailywtf.com/Articles/My-Tales.aspx) – Michael Stum Jul 09 '10 at 19:56
  • And it won't execute if the code doesn't compile and run, as this probably won't, because of the return statement. – DOK Jul 09 '10 at 19:56
  • 4
    @DOK What's wrong with the Return Statement? – Michael Stum Jul 09 '10 at 19:56
  • 5
    "... provided the application is still running." Great catch. – Zano Jul 09 '10 at 19:56
  • @ Michael Sturn As you might surmise from several comments, including the very first one below the question, the original code as posted would not have compiled. Apparently it just contained a typo, which has been fixed. – DOK Jul 09 '10 at 20:04
  • 4
    [It's good to keep this in mind - finally is *not* absolutely guaranteed.](http://thedailywtf.com/Articles/My-Tales.aspx) – Stephen Cleary Jul 09 '10 at 20:04
  • This is what Constrained Execution Regions (CER's) are for. – Greg D Jul 09 '10 at 20:07
  • There is one more scenario worth mentioning: if the code inside the try block never returns. Infinite loop for instance. – Remus Rusanu Jul 09 '10 at 20:10
  • ooh good call @Remus, I didn't think about that one. – kemiller2002 Jul 09 '10 at 20:14
  • 11
    @Remus: No, `finally` will get called as soon as the infinite loop completes... – Steven Sudit Jul 09 '10 at 20:14
  • 1
    Lol, yeah, we're all still waiting for the first ever infinite loop to complete ;) – Remus Rusanu Jul 09 '10 at 20:23
  • @Remus: While it does run at O(infinity), CPU speed makes all the difference! – Steven Sudit Jul 09 '10 at 20:25
  • @Steven well then thank goodness, I wrote my infinite loop to use all the cores in my system! – kemiller2002 Jul 09 '10 at 20:30
  • @Kevin: No, that's a mistake. The infinite loop is a purely single-threaded algorithm, so it does not benefit at all from parallelism. In fact, it's probably best if you only run it on a single core. – Steven Sudit Jul 09 '10 at 20:38
  • 1
    I'm sure there is some academik somewhere working on the problem of partitioning the infinite loop... Turing award is waiting! – Remus Rusanu Jul 09 '10 at 20:46
  • @Remus: The Google Indexer Robot is a fine example of a partitioned infinite loop. It not only spans cores but machines. – Steven Sudit Jul 09 '10 at 21:11
  • Years later, but I think the most voted answer needs to include that a stack overflow exception is normally not caught (even if you want) and that produces the `finally` block not to be executed. – Andrew Aug 31 '17 at 01:23
64

From MSDN C# specification of the try statement:

The statements of a finally block are always executed when control leaves a try statement. This is true whether the control transfer occurs as a result of normal execution, as a result of executing a break, continue, goto, or return statement, or as a result of propagating an exception out of the try statement.

Source

There are the cases where the finally block will not execute:

  1. Environment.FailFast
  2. Uncatchable exception types
  3. Power Failure
Stephen Kennedy
  • 20,585
  • 22
  • 95
  • 108
msarchet
  • 15,104
  • 2
  • 43
  • 66
  • @Gary Willoughby, I knew it did but I didn't want to be wrong so I just googled up the spec. – msarchet Jul 09 '10 at 19:59
  • The spec is wrong. Try this: static int Main( string[] arguments ) { try { return arguments[1000].Length; } finally { System.Console.WriteLine( "you will never see this!" ); } } – Mike Nakis May 31 '13 at 23:24
  • Wow, talk about bad answers to a good question.... This isn't a duplicate of the one indicated, because that question had to do with the finally block executing when there was a return statement in the try block, in which case the answer *is* "Yes". In the more general case per the title of this question, there are at least three different cases where the finally block will *not* be executed (even exclusive of outside influences such as a system crash, process being killed, etc.). See this question: http://StackOverflow.com/questions/19549613/finally-block-in-try-finally-does-not-execute – Rob at TVSeries.com Oct 23 '13 at 18:37
  • @Mike Nakis : I just tried your snippet. If you run it, "MyProgram has stopped working" window appear, if you click Cancel, it will display that line. (Built for Release) – Adam Szabo Nov 19 '13 at 12:38
  • user2270404: what you say illustrates my point: if you don't click Cancel, (if you click something else, or if you don't click anything at all,) the `finally` block will not be executed. – Mike Nakis Nov 20 '13 at 14:09
  • 2
    I thought that code in the finally block would signal the CPU to instruct the PSU to route the last bit of electrons stored in the reserve capacitors directly to the core running the finally code, in the event of a power failure (given a CLR-aware power supply of course). – Ronnie Overby Nov 20 '14 at 15:03
  • I know this is really old, but I hope someone answers, could anyone provide an example of an uncatchable exception? – Matheus Rocha Dec 12 '19 at 06:39
38

It is not totally true that finally will always be executed. See this answer from Haacked:

Two possibilities:

  • StackOverflowException
  • ExecutingEngineException

The finally block will not be executed when there's a StackOverflowException since there's no room on the stack to even execute any more code. It will also not be called when there's an ExecutingEngineException, which is very rare.

In fact, for any sort of asynchronous exception (like StackOverflowException, OutOfMemoryException, ThreadAbortException) the execution of a finally block is not guaranteed.

However, these exceptions are exceptions you usually cannot recover from, and in most cases your process will exit anyway.

In fact, there is also at least one other case where finally is not executed as described by Brian Rasmussen in a now deleted question:

The other case I am aware of is if a finalizer throws an exception. In that case the process is terminated immediately as well, and thus the guarantee doesn't apply.

The code below illustrates the problem

static void Main(string[] args) {
   try {
      DisposableType d = new DisposableType();
      d.Dispose();
      d = null;
      GC.Collect();
      GC.WaitForPendingFinalizers();
   } catch {
      Console.WriteLine("catch");
   } finally {
      Console.WriteLine("finally");
   }
}

public class DisposableType : IDisposable {
   public void Dispose() {
   }

   ~DisposableType() {
      throw new NotImplementedException();
   }
}

A reliable try/catch/finally will have to use Constrained Execution Regions (CER). An example is provided by MSDN:

[StructLayout(LayoutKind.Sequential)]
struct MyStruct
{
    public IntPtr m_outputHandle;
}

sealed class MySafeHandle : SafeHandle
{
    // Called by P/Invoke when returning SafeHandles
    public MySafeHandle()
        : base(IntPtr.Zero, true)
    {
    }

    public MySafeHandle AllocateHandle()
    {
        // Allocate SafeHandle first to avoid failure later.
        MySafeHandle sh = new MySafeHandle();

        RuntimeHelpers.PrepareConstrainedRegions();
        try { }
        finally
        {
            MyStruct myStruct = new MyStruct();
            NativeAllocateHandle(ref myStruct);
            sh.SetHandle(myStruct.m_outputHandle);
        }

        return sh;
    }
}

An excellent source of information is the following article:

Reliability Best Practices

Community
  • 1
  • 1
Dirk Vollmar
  • 172,527
  • 53
  • 255
  • 316
  • Could you please back up what you said about `ThreadAbortException` not triggering `finally`? – Steven Sudit Jul 09 '10 at 20:11
  • Agreed, I'm pretty sure ThreadAbortException does attempt to execute the finally block. It favors the finally block over actually aborting the thread, so the latter is less guaranteed than the former. – David Jul 09 '10 at 20:17
  • @Steven Sudit, @David: Sorry, I probably wasn't right about this. I somehow had this in the back of my head but MSDN clearly states that `finally` will be executed. – Dirk Vollmar Jul 09 '10 at 20:23
  • ThreadAbortException is a very unusual case, in that it can be caught, but gets automatically rethrown, unless the code has the rights required to call a method that suppresses the rethrow. Since there's this whole mechanism for dealing with it getting caught, it follows that it can't bypass `finally`. – Steven Sudit Jul 09 '10 at 20:27
  • You're right, of course, about `StackOverflowException` not triggering `finally`. However, under some circumstances, it doesn't kill the entire process, either. "An application that hosts the CLR can change the default behavior and specify that the CLR unload the application domain where the exception occurs, but lets the process continue." http://msdn.microsoft.com/en-us/library/w6sxk224(VS.90).aspx – Steven Sudit Jul 09 '10 at 20:36
  • @Steven Sudit: However, in case of an AppDomain unload execution of `finally` blocks is not guaranteed either. I think it's best explained in the following article, which also mentions the `ThreadAbortException`: [Reliability Best Practices](http://msdn.microsoft.com/en-us/library/ms228970.aspx) – Dirk Vollmar Jul 09 '10 at 20:48
  • 1
    It may also not execute when it's hit by Cosmic Rays! http://stackoverflow.com/questions/2580933/cosmic-rays-what-is-the-probability-they-will-affect-a-program – MaYaN Feb 02 '17 at 15:24
  • Just tested with debug&release - Example with finalizer actually calls the finally block before the finalizer itselft. – Curly Brace May 30 '18 at 14:45
  • 1
    @CurlyBrace: What you see is change introduced in .NET 4. Despite the call to `GC.WaitForPendingFinalizers()` the finalizer is run only at the end of the program. – Dirk Vollmar May 30 '18 at 16:04
5

From MSDN try-finally (C# Reference)

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. Control is always passed to the finally block regardless of how the try block exits.

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
4

yes it does :-) http://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx

Ian Jacobs
  • 5,456
  • 1
  • 23
  • 38
  • 56
    No, it doesn't. http://thedailywtf.com/Articles/My-Tales.aspx – Ivan Zlatanov Jul 09 '10 at 20:01
  • 7
    @IvanZlatanov The answer is correct in the context of the question, in which the OP apparently wants to know if finally will execute even after a return statement, however you are right that there are circumstances under which finally will not execute. – yoel halb Dec 10 '12 at 19:03
  • 1
    Oh, you would be surprised. Check this out: static int Main( string[] arguments ) { try { return arguments[1000].Length; } finally { System.Console.WriteLine( "you will never see this!" ); } } – Mike Nakis May 31 '13 at 23:22
  • 2
    @MikeNakis I tried and the finally message is shown. I am using .NET 4.5.1 – smwikipedia May 09 '14 at 07:35
  • 3
    If you place "Process.GetCurrentProcess().Kill();" or "Environment.FailFast("failfast");" in the try block, the finally block won't execute. And some unreleased resources or un-rolledback transactions may cause issue. – smwikipedia May 09 '14 at 07:37
  • @smwikipedia thanks for letting me know. Apparently, they fixed it in this version. (The one I tried back in may of 2013 was probably version 3.5.) – Mike Nakis May 10 '14 at 11:31
  • Finally will run always unless you call something like Environment.Exit() which kills the app right then and there, in which case Windows will cleanup your application memory and such so there's probably not a good reason you would need finally to run after you call an application killing method. – Trevor Hart Oct 13 '17 at 19:55
  • I imagine that if all your forground threads finish this could also result a finally blocks within worker threads to not always getting run (due to the process being shutdown) – andrew pate Jun 20 '18 at 10:55
2

Yes, under normal circumstances (as many others have pointed out).

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. Control is always passed to the finally block regardless of how the try block exits.

Whereas catch is used to handle exceptions that occur in a statement block, finally is used to guarantee a statement block of code executes regardless of how the preceding try block is exited.

http://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx

Zano
  • 2,595
  • 27
  • 33
2

The finally block will run, right between these lines:

message = "You will not win!";
return;
David Crowell
  • 3,711
  • 21
  • 28
1

No it doesn't.

There's only a single way around it though and that is Environment.FailFast(). See http://msdn.microsoft.com/de-de/library/ms131100.aspx. In every other case it is guaranteed that finalizers get executed ;-)

The FailFast method writes the message string to the Windows Application event log, creates a dump of your application, and then terminates the current process. The message string is also included in error reporting to Microsoft.

Use the FailFast method instead of the Exit method to terminate your application if the state of your application is damaged beyond repair, and executing your application's try/finally blocks and finalizers will corrupt program resources.

Johannes Rudolph
  • 35,298
  • 14
  • 114
  • 172
  • 2
    Anything that terminates the process outright instead of letting it close itself down gently is going to prevent `finally` from running. – Steven Sudit Jul 09 '10 at 20:12
0

Simple answer Yes. But there are some "exceptions" to the rule.

Jerod Houghtelling
  • 4,783
  • 1
  • 22
  • 30
0

Yes, finally always executes, now whether or not the code in the finally block will cause an exception is a different story.

Quintin Robinson
  • 81,193
  • 14
  • 123
  • 132
-1

The right answer is Yes.

Try to debug your program and put a break point and watch as control still hits the finally block.

JonH
  • 32,732
  • 12
  • 87
  • 145