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)
请注意,hidebysig
该Test(x,y)
方法没有属性.
该ECMA CLI规范有以下谈谈hidebysig
.(第15.4.2.2节,粗体强调是我的.)
hidebysig
提供工具使用, VES忽略.它指定声明的方法隐藏具有匹配方法签名的基类类型的所有方法; 省略时,该方法应隐藏所有同名方法,无论签名如何.
因此,F#编译器省略了该hidebysig
属性,这意味着该Test(x,y)
方法隐藏了所有其他命名的方法Test
.虽然hidebysig
只是"使用工具",但C#编译器似乎是使用它的工具之一!
这在我看来它可能是F#编译器中的一个错误,但由于我从未查看过F#规范,因此总是有可能这是允许/指定的行为.
归档时间: |
|
查看次数: |
546 次 |
最近记录: |