0
static void Main(string[] args)
{
    try
    {
        try
        {
            WriteLine("1  Entered try block");
            throw new ArithmeticException("EXC 1  InnerTry");
        }
        catch (Exception e)
        {
            WriteLine("2  Entered inner catch block, exception:");
            WriteLine(e.Message);
            throw new ArithmeticException("EXC 2  InnerCatch");
        }
        finally
        {
            WriteLine("3  Entered finally block.");
            throw new ArithmeticException("EXC 3  InnerFinally");
        }
    }
    catch (Exception e)
    {
        WriteLine("4  Entered outer catch block, exception:");
        WriteLine(e.Message);
    }            
}

For the above code, the output is

1  Entered try block
2  Entered inner catch block, exception:
EXC 1  InnerTry
3  Entered finally block.
4  Entered outer catch block, exception:
EXC 3  InnerFinally

Showing that the ArithmeticException("EXC 3 InnerFinally") in some sense overwrote the ArithmeticException("EXC 2 InnerCatch") exception.

However, in this code:

static void Main(string[] args)
{
    try
    {
        WriteLine("1  Entered try block");
        throw new ArithmeticException("EXC 1  InnerTry");
    }
    catch (Exception e)
    {
        WriteLine("2  Entered inner catch block, exception:");
        WriteLine(e.Message);
        throw new ArithmeticException("EXC 2  InnerCatch");
    }
    finally
    {
        WriteLine("3  Entered finally block.");
        throw new ArithmeticException("EXC 3  InnerFinally");
    }
}

The output is

1  Entered try block
2  Entered inner catch block, exception:
EXC 1  InnerTry
Unhandled exception. System.ArithmeticException: EXC 2  InnerCatch
   at ExceptionExample.Program.Main(String[] args) in D:\csharp\ExceptionExample.cs:line 77
3  Entered finally block.

so the finally exception is essentially ignored, and no information about it is displayed.

What is the reasoning behind this behaviour, and is it not quite inconsistent? I would assume that if a finally block is actually executed (no special circumstances where it might be skipped), then it will overwrite the exception, and the program would crash due to an unhandled ArithmeticException("EXC 3 InnerFinally") exception, but that's not the case. So what's happening? Perhaps it would help to clarify when exactly the finally blocks are executed - can we not assume that they will be executed before "stepping down" in the exception handling stack?

Jake1234
  • 187
  • 1
  • 7
  • 1
    See https://stackoverflow.com/a/2911229/43846 – stuartd Dec 01 '21 at 23:36
  • holup... "*so the finally exception is essentially ignored*" ? - https://dotnetfiddle.net/lPWPCH – TheGeneral Dec 01 '21 at 23:44
  • Also you might want to read this https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-finally – TheGeneral Dec 01 '21 at 23:50
  • @stuartd My question is about a specific situation, and I'm not getting the result that's described there. – Jake1234 Dec 01 '21 at 23:51
  • @TheGeneral I'm not sure what you posted is a reliable replication of what I've tried, as it doesn't look like the exception is unhandled - instead it looks like the runtime used there catches the exception and prints the stack trace, but I don't know. – Jake1234 Dec 01 '21 at 23:51
  • @TheGeneral: Your example's behavior changes if you switch to use .NET 6 as your compiler. – StriplingWarrior Dec 01 '21 at 23:53
  • Yes, which is why I pasted the documentation. It explains the unwind behaviour of finally and how you can deal with it – TheGeneral Dec 01 '21 at 23:55
  • @TheGeneral Yes, you are correct, it seems that finally execution for unhandled exceptions has special rules and could be OS dependent, and there there aren't any simple guarantees about what happens with finally blocks if an exception that will be unhandled gets thrown. Thank you and thanks for linking the documentation. – Jake1234 Dec 02 '21 at 00:15

0 Answers0