Take this code:
using System;
namespace OddThrow
{
class Program
{
static void Main(string[] args)
{
try
{
Next try:
I believe this case isn't mentioned in the c# standard and I agree it seems to almost contradict it.
I believe the internal reason why this is happening is somewhat like this: The CLR registers its default exception handler as SEH handler into FS:[0] when you have more catches in your code, those handlers are added to the SEH chain. Alternatively, only the CLR handler is called during SEH handling and handles the CLR exception chain internally, I don't know which.
In your code when the exception is thrown, only the default handler is in the SEH chain. This handler is called before any stack unrolling begins.
The default exception handler knows that there are no exception handler registered on the stack. Therefore it calls all registered UnhandledException handler first, then prints its error message and marks the AppDomain for unloading.
Only after that stack unrolling even begins and finally blocks are called according the c# standard.
As i see it, the way the CLR handles unhandled exception isn't considered in the c# standard, only the order in which finallys are called during stack unrolling. This order is preserved. After that the "The impact of such termination is implementation-defined." clause takes effect.