为什么重载方法的优先级低于实例方法
我有基础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为什么它不是扩展方法?
为什么编译器没有选择更合适的方法?
因为它遵循语言规范的规则,其中在查找候选方法时忽略最初在基类中声明的任何候选方法(如果它们在派生类中被覆盖,则忽略),除非派生类没有任何适用的方法,此时搜索移动到基类等。
这是为了避免“脆弱的基类”问题 ,但我发现面对在派生类中重写的方法很难吞下。
C#4规范的相关位是7.4,以此结束:
对于类型参数和接口以外的类型中的成员查找,以及严格单inheritance的接口中的成员查找(inheritance链中的每个接口都具有正好零或一个直接基接口),查找规则的效果就是派生成员隐藏具有相同名称或签名的基本成员。
编辑:关于扩展方法……
为什么它不是扩展方法?
从规范的7.6.5.2节:
在其中一个表单的方法调用(第7.5.5.1节)中
expr . identifier ( ) expr . identifier ( args ) expr . identifier < typeargs > ( ) expr . identifier < typeargs > ( args )
如果调用的正常处理找不到适用的方法,则尝试将该构造作为扩展方法调用进行处理
所以扩展方法基本上只作为最后的手段使用。