Есть такой код
static void Main(string[] args)
{
try { Console.WriteLine(1); throw new Exception(); }
catch(DivideByZeroException) { Console.WriteLine(2); }
finally { Console.WriteLine(3); }
Console.WriteLine(4);
}
Как видно, что здесь генерируется некоторое исключение, которое НЕ ловится блоком catch, по идее должен сработать finally - так как он срабатывает всегда не зависимо от того было исключение или нет. Но почему-то у меня он не выводит цифру 3 на консоль. Почему это может быть ?
Ответ
Это, как ни странно, ожидаемое поведение. Документация гласит:
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.
то есть
В случае пойманного исключения, блок finally гарантированно выполнится. Однако в случае если исключение не поймано, выполнение блока finally зависит от того, как именно была вызвана операция размотки стека. Это, в свою очередь, зависит от того, как настроен ваш компьютер.
В вашем случае как раз исключение не ловится, так что код в finally имеет право потеряться.
Ещё несколько случаев, когда блок finally не выполнится:
Было брошено достаточно «вредное» исключение:
StackOverflowException
исключения, свидетельствующие о повреждении состояния CLR, например, AccessViolationException, могут приводить к пропуску catch и finally
Код блока catch (или одного из фильтров исключений) может никогда не завершиться, например, войти в бесконечный цикл или бесконечное ожидание (deadlock).
Внутри блока catch (или одного из фильтров исключений) программа может быть завершена с использованием Environment.FailFast или Environment.Exit
Процесс может быть завершён операционной системой или другим процессом при помощи WinAPI-функции TerminateProcess. Ну или вашим же процессом тоже.
Операционная система может перестать функционировать. Например, питание компьютера может отключиться за время выполнения catch
Дополнение: Кажется, можно заставить выполниться блоки finally в случае необработанного исключения, используя дополнительный блок try/catch/throw вокруг всей программы:
try
{
try { Console.WriteLine(1); throw new Exception(); }
catch (DivideByZeroException) { Console.WriteLine(2); }
finally { Console.WriteLine(3); }
Console.WriteLine(4);
}
catch { throw; }
(Но я покамест не могу найти подтверждение этому в документации.)
За поведение размотки стека в отладчике отвечает вот эта настройка:
Комментариев нет:
Отправить комментарий