问题
In the given example (sorry for code style, it was in the interest of a compact self-contained repro), the method called is always the virtual method in B that has the additional integer parameter, while I would expect that the method implemented in C
would be the one called.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MethodChoosing
{
class Program
{
static void Main(string[] args)
{
C c = new C();
c.M();
Console.ReadKey();
}
}
public class A
{
public virtual void M(bool? a = null)
{
Console.WriteLine("base base");
}
}
public class B : A
{
public override void M(bool? a = null)
{
Console.WriteLine("base override");
}
public virtual void M(bool? a = null, int? b = null)
{
Console.Write("base new");
}
}
public class C : B
{
public override void M(bool? a = null)
{
Console.WriteLine("pick me!");
}
}
}
Which outputs "base new". This is obviously not the behaviour I expected, is anyone able to explain the reasoning?
Edit:
Changing main so that c.M
has a true or null parameter still selects the incorrect method.
回答1:
Section 7.4 of the spec states that override methods are excluded from the set of accessible methods being considered during member lookup. Considering the methods in the original question, class A has a single non overridden method, class B has a single non overridden method, and class C doesnt have any. From the two methods in the set, the compiler selects the matching method in the most derived class (in this case class B, the "base new" function).
If the matching function in class B were not present, the best function match would be the virtual function in class A. In that case, being virtual, the run time type of the object would be used to select which of the overridden functions in either class A, B or C would be chosen. Which as the question was stated, as the method was called on an object of class C, would be the "pick me!" function.
回答2:
That's whats called an Ambiguous Invocation. As you have two methods separated only by one optional parameter, the application seems to choose the method that it can satisfy the most parameters for.
Edit: as @lazyberezovsky stated, I wasn't entirely correct there. IF you have a method it can satisfy with NO parameters, that takes precedence
回答3:
With c.M()
it is assumed that M(null, null)
is called.
That is the way how optional parameters are working.
If you want C.M
to be called, call it with C.M(null)
or override M(bool? a = null, int? b = null)
in C
class.
来源:https://stackoverflow.com/questions/9890609/c-sharp-selecting-a-different-method-to-the-one-expected-with-optional-parameter