c# - 为什么 CLS 要求抛出/捕获异常派生对象?

标签 c# c++ .net clr cls

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

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

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

最佳答案

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

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

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

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

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

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

编辑

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

关于c# - 为什么 CLS 要求抛出/捕获异常派生对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30106176/

相关文章:

c++ - Qt错误: invalid use of incomplete type 'class QLabel'

c++ - 通过元素的功能搜索 upper_bound

.net - IronPython 性能

javascript - url 编码组件未进入字符串服务器端

c# - 从多个队列读取,RabbitMQ

c# - Linq where element.equals 一个数组

c# - 如何使用 Property List<IOBJ> 对对象进行 json 序列化或 json 反序列化?

c# - 如何检测 PictureBox 上是否按下了鼠标按钮?

c# - 如何在wpf mvvmlight中为datagrid实现 "nextpage"函数

c++ - 在 omnet++ IDE 中找不到 -lC :\SQLAPI\lib\sqlapi. 库