8

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

此外,如果某些不符合 CLS 的代码在被符合 CLS 的代码调用时抛出了非异常派生对象,会发生什么情况?

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

4

2 回答 2

5

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

允许抛出不符合 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 块。

于 2015-05-20T22:39:50.400 回答
2

为什么部分我无法回答,但第二部分我可以:

如果某些不符合 CLS 的代码在被符合 CLS 的代码调用时抛出了非 Exception 派生对象,会发生什么情况?

如果你抛出一个非异常派生的对象,它仍然会被符合 CLS 的代码捕获,因为它会被包装到一个RuntimeWrappedException.

源文章值得阅读以了解更多详细信息。)

于 2015-05-07T18:41:57.787 回答