3

In an inheritance hierarchy, I have the following generic method implemented:

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);
    }
}

The crucial part here is that in the method implementation in DerivedDerived I am invoking the method of the base class with a specific type (string).

When I compile this in Visual Studio (2012) or LinqPad and execute the following statement:

var x = new DerivedDerived().Foo<string>();

the output is what I intuitively expect:

Derived

However, if I compile and run the same code in Xamarin Studio 4.0 (Windows or Mac, on Windows it does not seem to matter if I compile and run with .NET or Mono C#), the output is:

Base

What would be the correct result here?

Paragraph 7.6.8 of the C# Language Specification 5.0 contains the following statement:

When a base-access references a virtual function member (a method, property, or indexer), the determination of which function member to invoke at run-time (§7.5.4) is changed. The function member that is invoked is determined by finding the most derived implementation (§10.6.3) of the function member with respect to B (instead of with respect to the run-time type of this, as would be usual in a non-base access). Thus, within an override of a virtual function member, a base-access can be used to invoke the inherited implementation of the function member. If the function member referenced by a base-access is abstract, a binding-time error occurs.

At first glance I would say that the most derived implementation, i.e. Derived.Foo, would be called from DerivedDerived.Foo, unless I somehow short-circuit the inheritance hierarchy by applying a specific type in the generic method invocation?

4

1 回答 1

1

The correct result is the following, which is clear from the way the specification is written.

Derived

Edit: The specification says:

The function member that is invoked is determined by finding the most derived implementation (§10.6.3) of the function member with respect to B (instead of with respect to the run-time type of this, as would be usual in a non-base access).

The base class of DerivedDerived is Derived. The most derived implementation of Foo<T> with respect to Derived is Derived.Foo<T>. That is the method which is called, not Base.Foo<T>.

于 2013-10-18T19:43:13.137 回答