无法解析已从C#重写和重载的F#方法

nxn*_*nxn 21 c# f# interop overriding overloading

以下F#代码声明了基类和后代类.基类有一个带有默认实现的虚拟方法'Test'.后代类重写基类方法,并添加新的重载'Test'方法.此代码编译良好,并且在访问后代'Test'方法时不会出现任何问题.

F#代码:

module OverrideTest
  [<AbstractClass>]
  type Base() =
    abstract member Test : int -> int
    default this.Test x = x + 1

  type Descendant() =
    inherit Base()
    override this.Test x    = x - 1
    member this.Test (x, y) = x - y
Run Code Online (Sandbox Code Playgroud)

但是,尝试从C#调用后代的'Test'覆盖会导致编译错误:

var result = td.Test(3); < - 方法'Test'没有重载需要1个参数

完整的C#代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Client
{
  class Program
  {
    static void Main(string[] args)
    {
      var td = new OverrideTest.Descendant();
      var result = td.Test(3);
      Console.WriteLine(result);
      Console.ReadKey();
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

奇怪的是,VisualStudio的intellisense看到了两个重载函数,并为两者提供了正确的签名.它在构建失败之前不会发出警告或错误,并且之后只会突出显示该行.

我已经在C#中完全重新实现了这个场景,并没有遇到同样的问题.

任何人都有任何想法在这里发生了什么?

Luk*_*keH 17

毫无疑问,你知道如果省略该类型的Test(x,y)成员Descendant- 或者只是重命名它Test2(x,y)- 那么C#代码将按预期编译和运行.

查看为原始Descendant类型生成的IL 提供了一条线索:

.method public hidebysig virtual
    instance int32 Test (
        int32 x
    ) cil managed ...

.method public 
    instance int32 Test (
        int32 x,
        int32 y
    ) cil managed ...
Run Code Online (Sandbox Code Playgroud)

请注意,hidebysigTest(x,y)方法没有属性.

ECMA CLI规范有以下谈谈hidebysig.(第15.4.2.2节,粗体强调是我的.)

hidebysig提供工具使用, VES忽略.它指定声明的方法隐藏具有匹配方法签名的基类类型的所有方法; 省略时,该方法应隐藏所有同名方法,无论签名如何.

因此,F#编译器省略了该hidebysig属性,这意味着该Test(x,y)方法隐藏了所有其他命名的方法Test.虽然hidebysig只是"使用工具",但C#编译器似乎是使用它的工具之一!

这在我看来它可能是F#编译器中的一个错误,但由于我从未查看过F#规范,因此总是有可能这是允许/指定的行为.