C#中的异常处理是否与ECMA-335标准相矛盾?

C#中的异常处理是否与ECMA-335标准相矛盾?,c#,.net,exception-handling,specifications,C#,.net,Exception Handling,Specifications,我的理解是基于支持C#规范中列出的行为的 CLI标准(EMCA-335)表明,如果没有合适的捕获,则运行时应立即终止。NET运行时并没有做到这一点,相反,它似乎倾向于C#规范(EMCA-334)的行为 首先,我觉得奇怪的是,语言规范似乎在定义框架行为。其次,它们似乎相互矛盾 它们是否相互矛盾,或者我是否理解了文件的错误含义 运行时是否必须以这种方式进行异常处理才能符合标准 作为一个可选问题,哪一个是“正确”的,例如,如果我要编写自己的CLI实现,我应该使用哪一个?请注意,EMCA-335(C

我的理解是基于支持C#规范中列出的行为的

CLI标准(EMCA-335)表明,如果没有合适的捕获,则运行时应立即终止。NET运行时并没有做到这一点,相反,它似乎倾向于C#规范(EMCA-334)的行为

首先,我觉得奇怪的是,语言规范似乎在定义框架行为。其次,它们似乎相互矛盾

  • 它们是否相互矛盾,或者我是否理解了文件的错误含义
  • 运行时是否必须以这种方式进行异常处理才能符合标准
作为一个可选问题,哪一个是“正确”的,例如,如果我要编写自己的CLI实现,我应该使用哪一个?请注意,EMCA-335(CLI)文档是在两个月前更新的,其中EMCA-334(C#)是在2006年更新的


  • 发生异常时,CLI将在阵列中搜索第一个发生异常的受保护块
    • 保护包括当前指令指针和
    • 是一个catch处理程序块和
    • 谁的筛选器希望处理该异常
  • 如果在当前方法中未找到匹配项,则搜索调用方法,依此类推。如果未找到匹配项,CLI将转储堆栈跟踪并中止程序

  • 如果找到匹配项,CLI会将堆栈返回到刚刚找到的点,但这次调用finally和fault处理程序。然后启动相应的异常处理程序

() 它与CLI标准之间的主要区别在于,无论是否找到catch块,应用程序都将不仅存在,而且仍将展开堆栈,并负责最终处理程序

我建议阅读标准本身,以便更好地理解这一点,因为下面是一个非常粗略的总结。它一步一步地概述了如何在每个可能的场景中执行try语句

  • 在引发异常的函数中:
    • 在每个try语句中查找匹配的catch子句
      • 执行catch语句(如果存在)
    • 如果存在finally块,则执行finally块
  • 如果没有处理程序,则在调用函数中重复上述步骤
  • 如果异常处理终止当前线程中的所有函数成员调用,表明该线程没有异常处理程序,则该线程本身终止。此类终止的影响由实施定义

这里没有冲突。C语言规范的措辞如下:

如果try语句没有catch子句,或者没有catch子句与异常匹配:
•如果try语句有finally块,则执行finally块。
•异常被传播到下一个封闭的try语句

这里的项目符号2没有特别说明当没有下一个包含try语句时会发生什么。为此,请转到8.9.5的末尾:

如果异常处理终止当前线程中的所有函数成员调用,表明该线程没有异常处理程序,则该线程本身终止。此类终止的影响由实施定义

它当然是实现定义的。除了Ecma 335规范之外,异常处理策略是Microsoft CLR中的一个可配置项。由ICLRPolicyManager::SetActionOnFailure()控制。反过来,可以在默认主机中使用
app.exe.config文件元素进行配置。CLR 2.0及以上版本的默认设置是立即终止程序


否则,这是相当徒劳无益的圣经解释学。所有这些对C#程序员来说都不应该感到惊讶,特别是考虑到测试是多么容易。

我认为这可能只是一个模糊的措辞问题

如果在当前方法中未找到匹配项,则搜索调用方法,依此类推。如果未找到匹配项,CLI将转储堆栈跟踪并中止程序

好吧,这在C中是正确的。我们都知道,如果我们没有一个
捕获
,那么一个异常将使我们的程序停止运行

如果找到匹配项,CLI会将堆栈返回到刚刚找到的点,但这次调用finally和fault处理程序。然后启动相应的异常处理程序

这也符合我们从C#知道的。如果有一些
最终
(我们看不到
故障
)块要处理,从抛出异常到捕获块,它们都会被处理,但它会停止,不再继续向上堆栈

我刚才引用的第二段节选的开头部分是“如果”,这一点在很大程度上取决于我们如何阅读。你读它的时候好像是“如果……那么……否则就没有这回事了”。它可以理解为识别堆栈中要走到的点的第一个摘录:如果有一个
捕获
,那么它就走到该点。如果没有捕获,那么它会走到堆栈的最顶端,我们得到一个转储并中止。最终的处理程序(和错误处理程序)仍然会被调用,但关键不是匹配的catch处理程序

你的阅读是最文字化的,而我的阅读是有点延伸的。然而,我的描述确实与同一标准中其他地方的描述相匹配,最接近的是O.p.中的基本假设不正确:

当然,我们不能在不考虑Windows的情况下讨论托管异常 结构化异常处理(SEH)。我们还需要看看C++异常。 模型这是因为实现了托管异常和C++异常。 最上面