.NET中的互操作性受损?

时间:2009-04-03 17:50:12

标签: c# .net interop f#

最近我在这里问了一个关于在C#中使用F#扩展的问题。布莱恩引用:

  

根据语言规范,第10.7节“类型扩展名”:

     

可选的扩展成员是静态成员的语法糖。可选扩展成员的使用精心调用具有编码名称的静态成员,其中对象作为第一个参数传递。此版本的F#中未指定名称编码,并且与C#扩展成员的C#编码不兼容。

我想知道.NET中是否存在任何其他互操作性问题,这些问题会将某些功能的使用局限于某些语言而不是其他语言?

4 个答案:

答案 0 :(得分:6)

我希望有很多东西,但是如果你在讨论主要的托管语言(C#,VB和很快的F#),那么大多数都是在极端情况下。 F#当前与C#交互性差的其他情况是当存在同时采用Action和Func的方法重载时(C#重载决策的工作方式与F#不同,因此对这种API的F#调用可能更加冗长); 'params'参数数组(特别是当试图利用'数组协方差'时,这是C#的一个特征而不是F#的特征);关于子类化或实现接口有一些问题,结合可访问性(例如公共与内部),有时你无法从C#中派生出一个F#类......

其中许多问题只是F#CTP编译器中的“错误”或F#语言规范的“设计问题”,可能会在F#的最终版本发布之前发生变化。

我不太了解CLR尘土飞扬的角落,但我敢打赌,有些地方C#和VB无法啮合。并且有一些主要语言都没有使用CLR的功能,因此我希望有一些方法可以创建有效的IL,这可能会导致某些互操作出现问题。

总的来说,我认为所有这些都是次要的,在F#的情况下,它会在最终版本之前被“修复”。但我很想知道人们会提到的其他内容,因为它可能对MS的托管语言团队提供有用的反馈。

答案 1 :(得分:2)

微软发布了一套guidelines来处理这类事情。基本上它适用于类设计者,并包括一些建议,例如不包括仅根据大小写区分的方法(对于像VB这样的不区分大小写的语言),为操作符重载时可能无法提供的替代方法等等。

答案 2 :(得分:2)

C ++ / CLI对CLR对象(不是引用,但是对象本身)具有“按值传递”语义,包括复制构造函数,临时对象及其销毁等。您可以编写:

ref class Foo {
public:
  Foo() { ... }
  Foo(Foo% other) { ... }
};

然后:

Foo^ getFooRef() { ... } // returns a reference to Foo
Foo getFoo() { ... } // returns a copy of Foo

当然,在CLR级别上它是所有引用--C ++ / CLI通过在您希望它们被调用的时刻调用构造函数,operator=和析构函数来模拟复制语义。在“按值返回”的情况下,这意味着调用者必须正确地破坏对象,引用它所接收的对象。 C#,VB和除C ++ / CLI之外的任何其他CLI语言都不知道如何操作,因此这些方法不能从它们调用。

另一个有趣的地方是CLR允许使用ref返回类型定义方法。没有CLR语言支持它们(甚至不支持C ++ / CLI),但您可以在MSIL中手动编写一个,并且不能从任何其他语言调用它。

通常,这种事情正是为什么创建公共语言规范(CLS)的原因。如果您遵守其规则,则不应存在任何语言的互操作性问题。

答案 3 :(得分:1)

从c#代码中消费 f#classes 有时会很棘手或烦人。

默认情况下,f#中的事件不是“正常”事件

添加[<CLIEvent>]属性解决了这个问题,除非你使用DelegateEvent而不是Event c# code must reference FSharpCore

头等舱功能的差异

在f#中使用FastFunc(f#函数的后端)创建委托很容易。 从c#中的委托制作FastFunc更令人烦恼,并且是touched on here。特别是Unit概念非常严重地映射回c#和Func / Action委托世界。

f#中定义的运算符很差,and inconsistently,在其他CLR语言中处理。这是CLR无法定义所需的复杂类型元数据的必然结果 操作员应被视为语言功能,并且不希望在不同语言之间进行良好的翻译。任何有用的运算符都应该具有等效的静态方法,该方法允许以一致且可移植的方式访问该功能。

类型推断

在f#中,这是无处不在的,因此你可能会发现一些非常复杂的类型被构造出来。一旦在c#中使用,这可能会变得很麻烦,因为对函数的类型推断不是那么强大,但是更糟糕的是它在构造函数中完全不存在,这会导致令人痛苦的冗长的c#代码。