CLS 比 CLR 更具限制性,它允许您抛出和捕获任何类型的对象(甚至是值类型)。为什么?
此外,如果某些不符合 CLS 的代码在被符合 CLS 的代码调用时抛出了非异常派生对象,会发生什么情况?
更新 @Marton 回答的第二个问题。仍然想知道为什么。
CLS 指定了许多应用程序所需的最小语言功能集,这样如果 API 仅使用这些功能,则任何符合 CLS 的语言都可以使用它。所以自然它比 CLR 更具限制性。另一方面,CLR 旨在处理来自任何符合 CLI 的语言的管理代码。
允许抛出不符合 CLS 的异常(不是从System.Exception派生的异常)的语言示例是 C++/CLI。该语言被设计为普通 C++ 的超集,其中包括抛出任何类型异常的能力。这可能是引发非 CLS 异常的唯一好理由。
关于第二个问题。一个非 CLS 异常,当抛出时,在不同的情况下会发生不同的事情:
在 CLR 2.0 及更高版本上,CLR 在内部始终将异常包装到System.Runtime.CompilerServices.RuntimeWrappedException中,该异常维护引用原始异常的Object类型的字段。这允许记录堆栈跟踪。当它向上传播堆栈时:
如果System.Runtime.CompilerServices.RuntimeCompatibilityAttribute属性应用于 CLR 在其中寻找匹配的 catch 块并且WrapNonExceptionThrows设置为 true(由 Visual C# 和 Basic 编译器自动应用)的函数的程序集,则异常继续被包裹。
否则,如果未应用该属性或WrapNonExceptionThrows设置为 false,则每次检查 catch 块是否匹配时都会解开异常。
编辑
在 C# 中,在上面的第一个项目符号和第二个项目符号的第二种情况下,捕获非 CLS 异常的唯一方法是使用无参数的 catch 块。
为什么部分我无法回答,但第二部分我可以:
如果某些不符合 CLS 的代码在被符合 CLS 的代码调用时抛出了非 Exception 派生对象,会发生什么情况?
如果你抛出一个非异常派生的对象,它仍然会被符合 CLS 的代码捕获,因为它会被包装到一个RuntimeWrappedException
.
(源文章值得阅读以了解更多详细信息。)