5

A simple console application, in Visual Studio 2019, .Net Framework 4.7, Windows:

static void Main(string[] args)
{
    try
    {
         Console.WriteLine("In try");
         throw new IndexOutOfRangeException();
    }
    finally
    {        *// Surprisingly this part is not being executed.*
         Console.WriteLine("In finally");
         Console.ReadLine();
    }                       
}

I was sure that finally block is being called in case of NO Exception, and in case of YES Exception. I've read in the docs:

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.

Link

Well, I'm confused. Do I need to do something with this "unwind operation" in order finally will be called in case of unhandled exceptions?

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
S Itzik
  • 494
  • 3
  • 12
  • [this](https://stackoverflow.com/questions/42250582/exception-handling-contradicting-documentation-try-finally-vs-using) and [this](https://en.wikipedia.org/wiki/Call_stack#Unwinding) – dontbyteme Nov 30 '20 at 08:11
  • This answer from Eric Lipper should clarify it: https://stackoverflow.com/a/4196863/5311735 – Evk Nov 30 '20 at 08:16
  • What I see after running this code: 1. In try 2. Unhandled Exception: ... 3. In finally | So what's the problem? – SᴇM Nov 30 '20 at 08:23
  • @SᴇM you should read the question again, i also popped it in dotnetfiddle and thought 'well this just works' but thats not what is asked here. – sommmen Nov 30 '20 at 08:24
  • @sem Did you run it in a Console application? Visual Studio 2019? – S Itzik Nov 30 '20 at 08:25
  • @SItzik Yes, I did. – SᴇM Nov 30 '20 at 08:26
  • May also depend on Platform. Is this .NET Framework or Core? What OS? (Framework, just realized, you stated it in question, sorry.) – Fildor Nov 30 '20 at 08:26
  • @Evk and dontbyteme thank you for your comments, but as you can see in your links, the replies were not accepted as answers, and they don't help me neither. Eric explain the logic behind not to run the finally, so what should we do in order to run the finally block in case of an Unhandled exception? – S Itzik Nov 30 '20 at 08:27
  • @sommmen I'm not sure about other parts of the question, but the title is pretty clear to me. Maybe OP needs to edit the question/title, to less confuse readers. – SᴇM Nov 30 '20 at 08:27
  • _"what should we do in order to run the finally block in case of an Unhandled exception?"_ Do you actually want to force-run the finally block, or do you want to "run _something_ in case of unhandled exception" ? ( See [AppDomain.UnhandledException Event](https://learn.microsoft.com/en-us/dotnet/api/system.appdomain.unhandledexception?view=net-5.0)) – Fildor Nov 30 '20 at 08:28
  • 2
    Eric says that you cannot rely on finally block being run on unhandled exception. In some cases it might run, in others not, so that's what you should do - not rely on it being run – Evk Nov 30 '20 at 08:30
  • 1
    @Fildor Good point. I added these details to the question, and about what is the goal: The goal is that finally block will run no matter if there was an exception or not (handled or unhandled) – S Itzik Nov 30 '20 at 08:31
  • 1
    Since the finally block may not run on unhandled exception, but (and i'm going off on the internet here) will go on when the exception is handled, why don't you just add an empty `catch` statement that catches all exceptions? – sommmen Nov 30 '20 at 08:34
  • I am not sure about the effect of it, but I'd try to register a handler for the UnhandledException event and see if that changes the treatment of the finally block. – Fildor Nov 30 '20 at 08:36
  • 2
    To the people that use dotnetfiddle to check. try changin the compiler version from .net 4.7.2 to .net core 5 and observe that in the latter the finally block is indeed not being run as op claims – sommmen Nov 30 '20 at 08:36
  • `The goal is that finally block will run no matter if there was an exception or not (handled or unhandled)` You can't, by definition. It it was possible then it would be guaranteed. But it isn't guaranteed. _OK, theoretically it could work even if it wasn't guaranteed - but even if it did, you couldn't **rely** on it working in the future._ – mjwills Nov 30 '20 at 08:36
  • 1
    `so what should we do in order to run the finally block in case of an Unhandled exception?` Catch it - to improve the odds that it isn't unhandled. – mjwills Nov 30 '20 at 08:40
  • 1
    My point was, that it works just fine on my machine, but may not work on a different one, with different configs. And as many people stated here, the unhandled exception is a different situation, when the system can decide to terminate your process. You cannot expect `finally` block to work if you for example unplug/power off your machine while the `try` code is running. – SᴇM Nov 30 '20 at 08:41
  • @mjwills yes, to add catches will do the job, but it seems it contradicts what I thought Finally is. Now I see that in some machines it work, in some machines it doesn't... Scary. Lets take for example the using clause. It creates behind the scenes try and finally without catch, in order to promise dispose...now by our discussion, even this is not promised... – S Itzik Nov 30 '20 at 08:47
  • _"now by our discussion, even this is not promised..."_ only in case of an (completely) unhandled exception, though. – Fildor Nov 30 '20 at 08:49
  • @SItzik You probably need to think this way - if your program runs "normally", in that case, `finally` will always be executed. – SᴇM Nov 30 '20 at 08:51
  • @Fildor, yes by the word "promised", I meant "any way" Unhandled exceptions or handled. The problem is that in some machines it will work and in some machines it will not work. So non accurate issue . – S Itzik Nov 30 '20 at 08:51
  • `even this is not promised...` Correct. – mjwills Nov 30 '20 at 08:51
  • 1
    `@Fildor, yes by the word "promised", I meant "any way" Unhandled exceptions or handled.` By definition you know that can't really work, not 100% - e.g. for stack overflow. Thus you are dealing with degrees of confidence, not absolutes. – mjwills Nov 30 '20 at 08:54
  • And I didn't even understand what configs I need to change in my machine in order the finally block will be called in such a case, like it was called to some of the users over here. – S Itzik Nov 30 '20 at 08:54
  • `And I didn't even understand what configs I need to change in my machine in order the finally block will be called in such a case,` Who said it was config related (I can't see that in the docs)? **If you want it more likely to be executed - add a `catch`**. – mjwills Nov 30 '20 at 08:55
  • @ mjwills Right, and for cases of I turn off the electricity, but I thought that at least in simple cases, Finally will be done any how, if the code leave the try block, and this is unfortunately not the case. – S Itzik Nov 30 '20 at 08:56
  • Well, you cannot "promise" to execute _any_ code, really. That's the nature of unhandled (=unexpected) events. If lightning strikes your machine, no whatever sophisticated mechanism is going to guarantee execution of any code... But I get what you thought should be possible to achieve ... – Fildor Nov 30 '20 at 08:57
  • 1
    `but I thought that at least in simple cases` And it does, in simple cases. The top of the call stack (e.g. Main) - debatable whether it is simple in that case. – mjwills Nov 30 '20 at 08:58
  • @mjwills, I will add catches, but what about the "using clause"? it doesn't use catch. Only try and finally. By our conclusion, I would except that behind the scenes, it will use a catch, for to be sure the object will be disposed. Isn't it? – S Itzik Nov 30 '20 at 08:59
  • No it doesn't use `catch` (and it isn't documented to use it). You could test this to validate it. https://dotnetfiddle.net/KIabGl – mjwills Nov 30 '20 at 09:05
  • @mjwills This is exactly what I say. The using clause doesn't use catch. Only try and Finally. So how can we be sure the Dispose() is going to be called? – S Itzik Nov 30 '20 at 09:07
  • @SItzik `So how can we be sure the Dispose() is going to be called?` You can't. As I said earlier. – mjwills Nov 30 '20 at 09:07
  • This answer https://stackoverflow.com/questions/111597/conditions-when-finally-does-not-execute-in-a-net-try-finally-block so not true by our discussion. – S Itzik Nov 30 '20 at 09:12
  • Is it fair to say that an answer written 12 years ago may not have considered the implications of running on a different runtime and / or a different OS? Yes, that would be fair to say. – mjwills Nov 30 '20 at 09:13
  • So actually there is not really a point in try and finally without using catches. – S Itzik Nov 30 '20 at 09:17
  • `there is not really a point` Sometimes seat belts don't help you survive a crash. And yet I wear one. Why? **Because usually they do**. There are limited situations where you need the catch. If this is a big deal for you **use the catch in those scenarios**. – mjwills Nov 30 '20 at 09:18
  • Usually? if in such a simple case it doesn't help when it does? Do you have an example of another simple case when try and finally without catch, actually cause the finally block to be called? – S Itzik Nov 30 '20 at 09:20

0 Answers0