It seems like it does as per some initial testing, but what I'd like to know is if it is guaranteed to return or if in some cases it can not return? This is critical for my application but I haven't found a use-case yet where it wouldn't return.
I'd like to get expertise on the subject.
-
2Some exceptions can't be caught like a stack overflow. – Michael Gattuso Apr 21 '12 at 02:55
-
See here: http://stackoverflow.com/a/50627/5190 – Vinko Vrsalovic Apr 21 '12 at 02:59
-
Can you over your scenario? Keep in mind that a program can be force terminated. From the title, it sounds like that you are asking if try { return; } finally { //mycode } will run the code in finally. The answer there is no. – David Z. Apr 21 '12 at 03:00
-
@DavidZ.: Actually, the answer is yes. http://ideone.com/RFZ2M – Ry- Apr 21 '12 at 03:02
-
2possible duplicate of [What really happens in a try { return x; } finally { x = null; } statement?](http://stackoverflow.com/questions/421797/what-really-happens-in-a-try-return-x-finally-x-null-statement) which not only answers this question but possibly most implied questions beyond the OP. – Erik Philips Apr 21 '12 at 03:04
-
@VinkoVrsalovic: That's not really as relevant, though, because the `return` never happens. – Ry- Apr 21 '12 at 03:04
-
I stand corrected :) Good to know, learn something more everyday :) – David Z. Apr 21 '12 at 03:07
-
@DavidZ. Well, if you read Eric's response you're not necessarily wrong. At least, in theory. – Brian Apr 23 '12 at 13:49
4 Answers
There are a number of inaccuracies in the other answers.
Control is passed to the finally block when control leaves the try block normally -- that is, by a return, goto, break, continue, or simply falling off the end. Control is passed to the finally block when control leaves the try block via an exception that has been caught by an enclosing catch block.
In every other circumstance there is no guarantee that the code in the finally block will be called. In particular:
If the try block code goes into an infinite loop, or the thread is frozen and never unfrozen, then the finally block code is never called.
If the process is paused in the debugger and then aggressively killed then the finally block is never called. If the process does a fail-fast then the finally block is never called.
If the power cord is pulled out of the wall then the finally block is never called.
If there is an exception thrown without a corresponding catch block then whether the finally block runs or not is an implementation detail of the runtime. The runtime can choose any behaviour when there is an uncaught exception. Both "do not run the finally blocks" and "do run the finally blocks" are examples of "any behaviour", so either can be chosen. Typically what the runtime does is ask the user if they want to attach a debugger before the finally blocks run; if the user says no then the finally blocks run. But again: the runtime is not required to do that. It could just fail fast.
You cannot rely on finally blocks always being called. If you require a strong guarantee about code executing then you should not be writing a try-finally, you should be writing a constrained execution region. Writing a CER correctly is one of the most difficult tasks in C# programming, so study the documentation carefully before you try to write the code.
Incidentally, a "fun fact" about finally-blocked gotos is:
try { goto X; } finally { throw y; }
X : Console.WriteLine("X");
X is an unreachable label targetted by a reachable goto! So next time you're at a party you can be like "hey everybody, can anyone make a C# program that has an unreachable label that is targetted by a reachable goto?" and you'll see who at the party has read the reachability specification and who has not!

- 2,059
- 1
- 19
- 36

- 647,829
- 179
- 1,238
- 2,067
-
I would add bugs: in runtime, OS, drivers, hardware etc. that caused BSOD or PC hangs. – Lukasz Madon Apr 21 '12 at 15:54
-
@EricLippert If outofMemory exception occurs in try block I think Finally will not be executed. Am I correct in assuming that? Please let me know. – Sandeep Apr 21 '12 at 19:25
-
39So the moral of the story is: Never invite Eric Lippert to your parties ;) – Tergiver Apr 23 '12 at 21:12
-
31@Tergiver: Little known fact: compiler developers throw the *best* parties. – Eric Lippert Apr 23 '12 at 22:12
-
-
-
What is so unusual about the `unreachable label that is targetted by a reachable goto`? Or maybe it does not seem like something unusual because I never thought about it before the post and now after the post I was shown a solution which is straightforward but hard to come up with (so, I skipped the hard part by reading the post) ? :) – qqqqqqq Mar 12 '20 at 19:44
-
@qqqqqqq: Because people generally think of "goto" as *instantly* transferring control from the current statement to the target statement. That intuition is false. Similarly people think of throw as *instantly* transferring control from the current statement to the matching catch block if there is no finally, but that's also false. Can you give an example of a program where there's a throw, there's a matching catch, there is no intervening finally, and control never gets to the body of the catch block? – Eric Lippert Mar 12 '20 at 22:07
-
@EricLippert, I can not. Could you, please, help me to do that? Maybe in the [fiddle](https://dotnetfiddle.net/)? :) – qqqqqqq Mar 12 '20 at 22:35
-
@qqqqqqq: Do you know what an *exception filter* is? When does it run? – Eric Lippert Mar 12 '20 at 22:51
-
@EricLippert, oh. Very cool. Never even heard about the feature. Thank you. I will check them out. (y) – qqqqqqq Mar 12 '20 at 22:55
-
@EricLippert, did you have in mind something similar to [this](https://dotnetfiddle.net/1a56Pm) when you gave the question about the unreachable `catch` block\`s body? :) – qqqqqqq Mar 12 '20 at 23:01
-
@qqqqqqq: Yes but go farther. Suppose instead of `false` you have `when M()` where `M()` is a function that goes into an infinite loop. The exception gets thrown, the exception filter runs to find out if the catch block handles it, but the filter runs forever so we never enter the catch block. – Eric Lippert Mar 12 '20 at 23:23
-
3@qqqqqqq: But here's the really nasty one. Suppose you have `void X() { try { ObtainAdminPowers(); DoSomethingDangerous(); } finally { ReleaseAdminPowers(); }}` and `DoSomethingDangerous` throws an exception. Now suppose we have `try { X(); } catch (Exception) when (M()) { }}`. The method `M()` runs *before* admin powers are released! The author of `X` believes that no code other than `DoSomethingDangerous` ever gets to use admin powers, but the author is wrong! – Eric Lippert Mar 12 '20 at 23:26
-
@EricLippert, I believe that the author of the `X()` should have defined the `Y()` as follows `void Y() { try { X(); } catch (Exception) when (M()) { }}` instead of giving out the bare `X()` :) – qqqqqqq Mar 13 '20 at 20:17
-
1@qqqqqqq: The correct mitigation in this case is the ridiculous `void X() { try { Obtain(); DoIt(); } catch { Release(); throw; } Release(); }` which no sensible person would write. It is one of the unfortunate security design flaws baked in to .NET exceptions. – Eric Lippert Mar 13 '20 at 21:20
-
@EricLippert, I created a [room](https://chat.stackoverflow.com/rooms/209619/try-catch-finally-in-net). Could you join, please? :) – qqqqqqq Mar 14 '20 at 09:53
-
@EricLippert: Is there any reason for `M()` to run before the `finally` block, or was it just a horrible mistake? I can't think of any good reason for it to work that way. – user2357112 Nov 19 '20 at 04:22
-
@user2357112supportsMonica: The decision is certainly questionable; I don't know if I would go so far as to say "horrible mistake". The principle here is: **you need to know if the exception is going to be caught** because if the answer is "no", then the CLR reserves the right to do stuff like activate debuggers or write crash dumps *as early as possible*, and that means before finally blocks. – Eric Lippert Nov 19 '20 at 19:20
-
@user2357112supportsMonica: People conceive of the control flow as being "run the finally blocks in order from most to least recent try block entered until you find a matching catch" but that's not what happens. The CLR finds the matching catch *first*, and *then* if one can be found, the finally blocks run. If a matching catch cannot be found then that triggers undefined behaviour and the CLR's disaster recovery mechanisms take over. – Eric Lippert Nov 19 '20 at 19:24
-
1@EricLippert Arguably the root cause is that `try { M } finally { N }` has the meaning different from `{ try { M } catch (Exception e) { N; throw; } N }`. I understand the motivation, but can't help to wonder if it could be achieved without introducing the entirely separate exception-related primitive. – Joker_vD Nov 21 '20 at 12:09
-
Wow, I never would have expected that a `finally` block would still be executed when `return`ing early :O That's really handy for my model-save functions though; it allows me to reset the UI correctly whether I have to return early due to detecting an invalid state or I catch an exception. – Clonkex May 13 '22 at 00:14
Under normal conditions, code in a finally block will be executed regardless of what happens inside the try or catch blocks. It doesn't matter if you return from the method or not.
There are cases where this is not true. For example if the code in the finally block throws an exception, then it will stop executing like any other block of code.
Eric Lippert has written a much more comprehensive answer that outlines additional cases: https://stackoverflow.com/a/10260233/53777
In regards to goto, the answer is still yes. Consider the following code:
try
{
Console.WriteLine("Inside the Try");
goto MyLabel;
}
finally
{
Console.WriteLine("Inside the Finally");
}
MyLabel:
Console.WriteLine("After the Label");
The output produced is this:
Inside the Try
Inside the Finally
After the Label

- 17,133
- 6
- 43
- 60
Here are some examples:
Environment.FailFast()
try
{
Console.WriteLine("Try");
Environment.FailFast("Test Fail");
}
catch (Exception)
{
Console.WriteLine("catch");
}
finally
{
Console.WriteLine("finally");
}
The output is only "Try"
Stackoverflow
try
{
Console.WriteLine("Try");
Rec();
}
catch (Exception)
{
Console.WriteLine("catch");
}
finally
{
Console.WriteLine("finally");
}
Where Rec is:
private static void Rec()
{
Rec();
}
The output is only "Try" and the process terminates due to StackOverflow.
Unhanded exception
try
{
Console.WriteLine("Try");
throw new Exception();
}
finally
{
Console.WriteLine("finally");
}

- 14,664
- 14
- 64
- 108
-
3The last example (**Unhanded exception**) actually executes `finally` block. – N. M. Nov 30 '20 at 21:08
In case of fatal exceptions that terminate application Finally block will not be called. Includes stack overflow, exceptions during JIT of methods to call, fatal exceptions insisde CLR runtime.
As @mintech points out if application hangs inside the block it simply will not reach finally block. This includes waiting for synchronization objects, deadlocks infinite loops or even UI that does not have a way to close it.

- 98,904
- 14
- 127
- 179