我有基类A
public class A
{
public virtual void Method(A parameter)
{
Console.WriteLine(MethodBase.GetCurrentMethod());
}
public virtual void Method(B parameter)
{
Console.WriteLine(MethodBase.GetCurrentMethod());
}
}
内在B
public class B : A
{
public virtual void Method(object parameter)
{
Console.WriteLine(MethodBase.GetCurrentMethod());
}
public override void Method(A parameter)
{
Console.WriteLine(MethodBase.GetCurrentMethod());
}
public override void Method(B parameter)
{
Console.WriteLine(MethodBase.GetCurrentMethod());
}
}
具有扩展方法的静态类S
public static class S
{
public static void Method(this B instance, B parameter)
{
Console.WriteLine(MethodBase.GetCurrentMethod());
}
}
示例我们创建了B
类型的实例并在其上调用Method
,我们希望public override void Method(B parameter)
实际结果为public virtual void Method(object parameter)
。
var b = new B();
b.Method(new B()); // B.Method (Object parameter) Why???
为什么编译器没有选择更合适的方法??? UPD 为什么它不是扩展方法?
答案 0 :(得分:10)
为什么编译器没有选择更合适的方法?
因为它遵循语言规范的规则,其中任何候选方法最初在基类中声明(如果它们在派生类中被覆盖)将在查找候选方法时被忽略,除非派生类没有任何适用的方法,否则搜索会移动到基类等等。
这是designed to avoid the "brittle base class" problem,但我发现在派生类中重写方法时难以接受。
C#4规范的相关位是7.4,以此结束:
对于类型参数和接口以外的类型中的成员查找,以及严格单继承的接口中的成员查找(继承链中的每个接口都具有正好零或一个直接基接口),查找规则的效果是只是派生成员隐藏具有相同名称或签名的基本成员。
编辑:关于扩展方法......
为什么它不是扩展方法?
来自规范的第7.6.5.2节:
在其中一种形式
的方法调用(第7.5.5.1节)中expr . identifier ( ) expr . identifier ( args ) expr . identifier < typeargs > ( ) expr . identifier < typeargs > ( args )
如果调用的正常处理找不到适用的方法,则尝试将构造作为扩展方法调用进行处理
因此,扩展方法仅用作最后的手段,基本上。