我很久以前就遇到过这样的类型CLSCompliantAttribute
。思路很简单:限制高级语言的接口,让相对低级的语言与之交互。但是当我从 .NET Framework 切换到 .NET Core 时,结果发现 Microsoft 的扩展(按类型Microsoft.Extensions.Configuration
)不符合 CLS。
那么一个合乎逻辑的问题就出现了:既然CLSCompliantAttribute
连它的创造者都不使用它,为什么在 2020 年还需要它呢?
有没有没有它就活不下去的语言?
语言本质上并不关心这个属性。语言需要它们消化的 API,并且它们可以在尝试使用不受支持的 API 时使用 CLSCompliant 属性发出编译时警告。或者他们可能不会使用它。现实更接近第二种选择。为了说明这一点,让我们为“低级”C# 和高级 JScript.NET 之间的互操作性创建一个实验性蓝图:
为此,您需要添加对 Microsoft.JScript 的引用(并且项目必须是 .NET Framework - .NET Core 没有与 JS 集成所需的类型)。实际上,代码从文件中获取脚本,通过反射编译和运行。我提请您注意,
results.Errors
除了错误之外,它还包括警告,因此我们将看到编译器 (jsc) 生成的所有内容。现在在它的帮助下,我们可以通过 JS 运行有趣的 API 并查看它的行为方式。实验 1 - UInt32
让我们从简单的开始 - 让我们尝试将“不合规”的 UInt32 提供给 JS:
JS:
C#:
如您所见,一切正常,没有错误。实际上,这并不能真正证明什么,因为 JScript.NET 与浏览器等价物不同,它本机支持 uint ( https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio- 2010/ ddacxdt5%28v%3dvs.100%29)。但至少我们的实验代码有效。
实验 2 - Microsoft.Extensions.Configuration
考虑提到的 Microsoft.Extensions.Configuration。幸运的是,它与新版本的 .NET Framework 兼容。为了检查,让我们编写以下 JS 代码来创建 ConfigurationBuilder,在 Properties 字典中设置值并尝试将其读回:
C#:
同样,一切都很好。好吧,这也没什么好奇怪的——所有类型都属于 JS 类型系统。
实验 3 - 指针
现在让我们来看看 JS 并不真正支持的东西——指针。当然,我们甚至不能直接传递指针,但是有像Pointer .Box / Unbox、IntPtr 这样的 API 允许您包装指针以进行反射。正如您可能猜到的那样,它们是 CLSCompliant(false)。让我们编写一个将指针传递给 JS 的代码,在 JS 代码中,我们将尝试使用其中可用的工具来处理它:
JS:
C#
如您所见,使用 2 种方法和 CLSCompliant(false) 不仅没有警告,而且代码成功地能够通过指针设置变量的值。线索是在幕后一切都在反射上起作用,而 JS 从来没有遇到过直接创建指针变量的需要。这并不意味着指针上的任何 API 都可以以这种方式使用。如果 API 不接受 void*,但假设是 byte*,则不再清楚如何转换它。
简而言之,CLSCompliantAttribute 在当今.NET 世界中的价值并没有那么大。与真正的语言集成相比,更需要关闭 C# 编译器本身并分离 FxCop 分析器,这些分析器发誓没有它。有些人选择忽略警告并且不设置属性以保存二进制大小。但是如果只是删除该属性,那么依赖它的代码就会崩溃,从而导致“连创作者都不需要它,但不要删除它”的情况。