为什么CLS要求抛出/捕获Exception派生对象?

时间:2015-05-07 15:59:15

标签: c# c++ .net clr cls

CLS比CLR更具限制性,它允许您抛出并捕获任何类型的对象(甚至是值类型)。为什么呢?

如果一些非符合CLS的代码在符合CLS的代码调用时抛出非异常派生对象会发生什么?

更新 第二个问题由@Marton回答。仍然想知道为什么。

2 个答案:

答案 0 :(得分:5)

CLS指定了许多应用程序所需的最小语言功能集,如果API仅使用这些功能,则它可以被任何符合CLS的语言使用。所以自然它比CLR更具限制性。另一方面,CLR设计用于处理来自任何CLI兼容语言的manged代码。

允许抛出非CLS兼容异常(不是从 System.Exception 派生的异常)的语言示例是C ++ / CLI。这种语言被设计成普通C ++的超集,它包括抛出任何类型的异常的能力。这可能是抛出非CLS异常的唯一理由。

关于第二个问题。抛出非CLS异常时,在不同情况下会发生不同的事情:

  • 如果CLR 1.X正在管理代码的执行,则异常按原样传播。在仅支持CLS异常(C#)的语言中,异常只能由无参数的catch块捕获。没有简单的方法来访问异常,并且不会记录堆栈跟踪。
  • 在CLR 2.0及更高版本中,CLR内部始终将异常包装到 System.Runtime.CompilerServices.RuntimeWrappedException 中,该字段维护 Object 类型的字段引用原始异常。这允许记录堆栈跟踪。当它向上传播时:

    1. 如果 System.Runtime.CompilerServices.RuntimeCompatibilityAttribute 属性应用于CLR正在寻找匹配的catch块并且 WrapNonExceptionThrows 设置为true(由Visual C#和Basic编译器自动应用),然后异常继续被包装。

    2. 否则,如果未应用该属性或 WrapNonExceptionThrows 设置为false,则每次检查catch块进行匹配时都会解除该异常。

修改

在C#中,在上面的第一个项目符号和第二个项目符号的第二个案例中,捕获非CLS异常的唯一方法是使用无参数的catch块。

答案 1 :(得分:2)

为什么我不能回答,但第二部分我可以:

  

如果某些非符合CLS的代码抛出非异常会发生什么   由符合CLS的代码调用派生对象?

如果抛出一个非Exception派生的对象,它仍然会被符合CLS的代码捕获,因为它将被包装到RuntimeWrappedException中。

source article值得阅读以获取更多详细信息。)