Ответ 1
Возможно, вас научили тому, что при обработке исключений каждый метод рассматривается отдельно. То есть, поскольку ваш внутренний метод имеет try...finally
, любое исключение сначала вызывает finally
, а затем будет "смотреть" на try
выше. Это неверно.
Из спецификации ECMA CLR (ECMA-335, I.12.4.2.5 Обзор обработки исключений):
Когда возникает исключение, CLI ищет массив для первого защищенного блока, который
- Защищает регион, включая текущий указатель инструкции, и
- Является блоком обработчика catch и
- Чей фильтр хочет обработать исключение
Если совпадение не найдено в текущем методе, выполняется поиск метода вызова и т.д. Если совпадение не найдено, CLI удалит трассировку стека и прервет работу программы.
Если совпадение найдено, CLI переводит стек обратно в только что находящуюся точку, но на этот раз вызывает обработчики finally и fault. Затем он запускает соответствующий обработчик исключений.
Как вы можете видеть, поведение на 100% соответствует спецификации.
- Найдите защищенный блок -
try
вSomeOperation
- Есть ли у него блок обработчика catch? Нет.
- Найдите защищенный блок в вызывающем методе -
try
вMain
- Есть ли у него блок обработчика catch? Да!
- Может ли фильтр обрабатывать исключение? Фильтр оценивается (отказ от ответственности: это не означает, что все фильтры в защищенном блоке всегда будут оцениваться - не проблема, если фильтр не имеет побочных эффектов, чего он действительно не должен, конечно), и результат да.
- Пройдите обратно в стек и выполните все обработчики finally и fault
-
finally
вSomeOperation
-
finally
в Main
не является частью этого, конечно же - он будет выполняться, когда выполнение выходит из защищенного блока, независимо от исключения.
EDIT:
Просто для полноты - это всегда было так. Единственное, что изменилось, это то, что С# теперь поддерживает фильтры исключений, что позволяет вам наблюдать за порядком выполнения. VB.NET поддерживает фильтры исключений из версии 1.