【发布时间】:2012-08-23 12:36:55
【问题描述】:
我的理解基于this long, but fantastic, article,它支持 C# 规范中列出的行为。
CLI 标准 (ECMA-335) 表明,如果没有合适的 catch,运行时应立即终止。 .NET 运行时不这样做,相反,它似乎倾向于 C# 规范 (EMC-334) 的行为。
首先,我觉得奇怪的是语言规范似乎在定义框架行为。其次,他们似乎矛盾。
- 它们是否相互矛盾,或者我理解了文档的错误含义?
- 运行时是否必须以这种方式进行异常处理才能符合标准?
作为一个可选问题,哪一个是“正确”的,例如,如果我要编写自己的 CLI 实现,我应该使用哪一个?请注意,EMCA-335 (CLI) 文档是两个月前更新的,而 EMCA-334 (C#) 是在 2006 年更新的。
ECMA-335 Partition I Section 12.4.2.5
- 发生异常时,CLI 会在数组中搜索第一个受保护的块
- 保护包含当前指令指针的区域和
- 是一个 catch 处理程序块,并且
- 谁的过滤器希望处理异常
如果在当前方法中未找到匹配项,则搜索调用方法,依此类推。如果未找到匹配项,CLI 将转储堆栈跟踪并中止程序。
如果找到匹配项,CLI 将堆栈返回刚刚找到的点,但这次调用 finally 和错误处理程序。然后它启动相应的异常处理程序。
C# Specification §15.9.5 and §15.10 (§8.9.5 and §8.10 on MSDN)
它与 CLI 标准的主要区别在于,无论是否找到了 catch 块,应用程序不仅会存在,而且仍会展开堆栈,并处理 finally 处理程序。
我建议阅读标准本身以更好地理解这一点,因为下面是一个非常粗略的总结。它逐步概述了如何在每种可能的情况下执行 try 语句。
- 在引发异常的函数中:
- 在每个 try 语句中查找匹配的 catch 子句
- 如果存在则执行 catch 语句
- finally 块在存在时执行
- 如果没有处理程序,则在调用函数中重复上述步骤
- 如果异常处理终止了当前线程中的所有函数成员调用,表明该线程没有异常的处理程序,则该线程本身终止。这种终止的影响是由实现定义的。
【问题讨论】:
-
+1 不仅要彻底阅读一份规范,还要阅读两份!也很有趣的问题:)
-
如果线程终止(或中止程序),异常不会传播到 try 语句之外并且没有控制离开 try 语句——线程只是结束控制。我不认为有矛盾。
标签: c# .net exception-handling specifications