为什么 CLS 要求 Exception 派生对象的 throwing/catching?

Why the CLS mandates the throwing/catching of Exception derived objects?

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

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

更新 @Marton 回答的第二个问题。还在想为什么。

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

what would happen if some non CLS-compliant code threw a non Exception derived object while called by a CLS compliant code?

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

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

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 中,它维护一个类型为 [=26= 的字段]Object 引用原始异常。这允许记录堆栈跟踪。当它向上传播堆栈时:

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

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

编辑

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