泛型方法继承:VS 和 Xamarin Studio 产生不同的结果;这是对的
本文关键字:结果 VS 继承 Xamarin Studio 泛型方法 | 更新日期: 2023-09-27 18:36:01
在继承层次结构中,我实现了以下通用方法:
public class Base
{
public virtual T Foo<T>()
{
Console.WriteLine("Base");
return default(T);
}
}
public class Derived : Base
{
public override T Foo<T>()
{
Console.WriteLine("Derived");
return default(T);
}
}
public class DerivedDerived : Derived
{
public override T Foo<T>()
{
base.Foo<string>();
return default(T);
}
}
这里的关键部分是,在DerivedDerived
的方法实现中,我调用了具有特定类型(string
)的基类的方法。
当我在Visual Studio(2012)或LinqPad中编译它并执行以下语句时:
var x = new DerivedDerived().Foo<string>();
输出是我直观期望的:
Derived
但是,如果我在 Xamarin Studio 4.0(Windows 或 Mac,在 Windows 上编译和运行 .NET 或 Mono C# 似乎无关紧要)中编译并运行相同的代码,则输出为:
Base
这里的正确结果是什么?
C# 语言规范 5.0 的第 7.6.8 段包含以下语句:
当基本访问引用虚函数成员(方法, 属性或索引器),确定哪个函数成员 运行时调用 (§7.5.4) 已更改。函数成员是 调用是通过查找派生最多的实现来确定的 (§10.6.3) 的函数成员相对于 B(而不是 关于这种运行时类型,就像在非基库中一样 访问)。因此,在虚函数成员的覆盖中,一个 基访问可用于调用继承的实现 函数成员。如果基访问引用的函数成员是 摘要,发生绑定时间错误。
乍一看,我会说最派生的实现,即 Derived.Foo
,将从DerivedDerived.Foo
调用,除非我通过在泛型方法调用中应用特定类型以某种方式缩短继承层次结构?
正确的结果如下,从规范的编写方式中可以清楚地看出。
Derived
编辑:规范说:
调用的函数成员是通过查找函数成员相对于 B 的最派生实现 (§10.6.3) 来确定的(而不是相对于运行时类型,这在非基本访问中很常见)。
DerivedDerived
的基类是 Derived
。关于Derived
的Foo<T>
派生最多的实现是Derived.Foo<T>
。这是所谓的方法,而不是Base.Foo<T>
。