在继承层次结构中,我实现了以下通用方法:
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
)的 base 类的方法。
当我在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段包含以下声明:
当base-access引用虚函数成员时(一种方法, property或indexer),确定哪个函数成员 在运行时调用(第7.5.4节)已更改。函数成员是 通过查找派生最多的实现来确定调用 关于B的函数成员的(第10.6.3节)(而不是 尊重它的运行时类型,就像在非基数中一样 访问)。因此,在虚拟功能成员的覆盖范围内,a base-access可用于调用继承的实现 功能成员。如果base-access引用的函数成员是 abstract,发生绑定时错误。
乍一看,我会说从Derived.Foo
调用派生最多的实现,即DerivedDerived.Foo
,除非我通过在泛型方法中应用特定类型以某种方式使继承层次结构短路调用
答案 0 :(得分:1)
正确的结果如下:从编写规范的方式可以清楚地看出。
Derived
编辑:规范说:
调用的函数成员是通过查找函数成员相对于B的最多派生实现(第10.6.3节)来确定的(而不是相对于它的运行时类型,通常在非基本访问)。
DerivedDerived
的基类是Derived
。 Foo<T>
关于Derived
的派生程度最高的实现是Derived.Foo<T>
。这是被称为的方法,而不是Base.Foo<T>
。