4

I have this console application (.NET Framework 4.5.2):

class Program
{
    static void Main(string[] args)
    {
        using (var result = new Result())
        {
            result.Test();
        }
    }
}

public class Result : IDisposable
{
    public void Test()
    {
        int a = 1;
        int b = 1 / (a - 1);
    }

    public void Dispose()
    {
        Console.WriteLine("Dispose");
    }
}

Why Dispose method is not called? A breakpoint is not hit in Dispose after the DivideByZero-exception and there is no output on the console (because the app exits).

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939

1 Answers1

11

As per MS Docs: try-finally (C# Reference)

Within a handled exception, the associated finally block is guaranteed to be run. 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.

As you are not catching the DivideByZero exception and let it be unhandled, on your machine and setup it must be bringing down the application before any other line of code is run and therefore not running the finally block.

As @Evk has pointed out in below comment, if I run it without attaching debugger, it unwinds the exceptions correctly and executes the finally block. Learn something new everyday.

As per Eric Lippert's answer to Finally Block Not Running?

Think about how awful that situation is: something unexpected has happened that no one ever wrote code to handle. Is the right thing to do in that situation to run even more code, that was probably also not built to handle this situation? Possibly not. Often the right thing to do here is to not attempt to run the finally blocks because doing so will make a bad situation even worse. You already know the process is going down; put it out of its misery immediately.

In a scenario where an unhandled exception is going to take down the process, anything can happen. It is implementation-defined what happens in this case: whether the error is reported to Windows error reporting, whether a debugger starts up, and so on. The CLR is perfectly within its rights to attempt to run finally blocks, and is also perfectly within its rights to fail fast. In this scenario all bets are off; different implementations can choose to do different things.

Michal Ciechan
  • 13,492
  • 11
  • 76
  • 118
  • No not always, certain exceptions cause app to completely shut down (e.g. Hardware exceptions). Would of expected this to run the finally block, but I can confirm on my machine it doesn't ever enter the Finally block – Michal Ciechan Nov 07 '17 at 09:15
  • 1
    Your wording is misleading, because you say that this finally _never_ gets run, while this is not true (your own quote says that "it depends"). – Evk Nov 07 '17 at 09:22
  • 2
    It also MUCH more likely that OP runs application under debugger in which case VS will terminate process on unhandled exception (will not unwind it). If OP runs without debugger on the same machine and configuration - it will execute finally block. – Evk Nov 07 '17 at 09:26
  • 1
    @Evk I think you should post that as an answer, as to me I would expect the debugger to run finally block if anything, rather than without it. Thanks for pointing out and can confirm on my machine that your statement is true. Do you know if that is always the case? – Michal Ciechan Nov 07 '17 at 09:46
  • 2
    As far as I know - visual studio debugger always "kills" process after unhandled exception, don't know if there are any ways to avoid that. You can emulate the same with `Environment.FailFast` for example. If you do `try { ... some stuff ...; Environment.FailFast("some message");} finally {}` then finally block will not be run even without debugger. Or you can kill process from task manager. – Evk Nov 07 '17 at 09:53
  • I think your answer is fine in general case, after all as your Eric Lippert quote says - it's all implementation dependent. – Evk Nov 07 '17 at 09:54