Мое понимание основано на этой длинной, но фантастической статье, которая поддерживает поведение, указанное в спецификации С#.
Стандарт CLI (EMCA-335) показывает, что если подходящего улова нет, время выполнения должно немедленно прекратиться. Время выполнения .NET не делает этого, вместо этого оно, похоже, склоняется к поведению спецификации С# (EMCA-334).
Во-первых, мне кажется странным, что спецификация языка, как представляется, определяет поведение каркаса. Во-вторых, они, кажется, противоречат.
- Они противоречат друг другу, или я получаю неправильный смысл документа?
- Должно ли время выполнения работать с обработкой исключений, чтобы соответствовать стандарту?
Как необязательный вопрос, какой из них является "правильным", как в случае, если я должен написать свою собственную реализацию CLI, которую я должен использовать? Обратите внимание, что документ EMCA-335 (CLI) был обновлен два месяца назад, где EMCA-334 (С#) был обновлен еще в 2006 году.
ECMA-335 Раздел я Раздел 12.4.2.5
- Когда возникает исключение, CLI ищет массив для первого защищенного блока, который
- Защищает регион, включая текущий указатель инструкции, и
- Является блоком обработчика catch и
- Чей фильтр хочет обработать исключение
Если совпадение не найдено в текущем методе, выполняется поиск вызывающего метода и т.д. Если совпадение не найдено, CLI удалит трассировку стека и прервет работу программы.
Если совпадение найдено, CLI переводит стек обратно в только что находящуюся точку, но на этот раз вызывает обработчики finally и fault. Затем он запускает соответствующий обработчик исключений.
С# Спецификация §15.9.5 и §15.10 (§8.9.5 и §8.10 на MSDN)
Основное различие между ним и стандартом CLI заключается в том, найден ли или нет блок catch, приложение будет не просто существовать, но все равно будет разматывать стек и позаботиться о последствиях обработчиков.
Я бы посоветовал сначала прочитать стандарт, чтобы лучше понять это, так как ниже это очень грубое резюме. В нем описывается шаг за шагом, как выполняется оператор try с каждым возможным сценарием.
- В функции, которая вызывает исключение:
- Ищет соответствующее предложение catch в каждом заявлении try
- Выполняет оператор catch, если он существует
- Блок finally выполняется, если он существует
- Если не было обработчика, вышеуказанные шаги повторяются в вызывающей функции
- Если обработка исключений завершает все вызовы членов функции в текущем потоке, указывая, что поток не имеет обработчика исключения, то сам поток завершается. Влияние такого завершения определяется реализацией.