11

我有基类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为什么它不是扩展方法?

4

1 回答 1

10

为什么编译器不选择更合适的方法?

因为它遵循语言规范的规则,在找到候选方法时,最初在基类中声明的任何候选方法(如果它们在派生类中被覆盖)都会被忽略,除非派生类没有任何适用的方法,此时搜索向上移动到基类等。

这是为了避免“脆弱的基类”问题而设计的,但是面对派生类中被覆盖的方法,我发现很难接受。

C# 4 规范的相关位是 7.4,其结尾是:

对于类型参数和接口以外的类型中的成员查找,以及严格单继承的接口中的成员查找(继承链中的每个接口恰好有零个或一个直接基接口),查找规则的效果只是派生的成员隐藏具有相同名称或签名的基本成员。

编辑:关于扩展方法...

为什么它不是扩展方法?

从规范的第 7.6.5.2 节:

在其中一种形式的方法调用(§7.5.5.1)中

expr . identifier ( )
expr . identifier ( args )
expr . identifier < typeargs > ( )
expr . identifier < typeargs > ( args )

如果调用的正常处理未找到适用的方法,则尝试将构造处理为扩展方法调用

所以扩展方法基本上只是作为最后的手段使用。

于 2012-08-24T13:41:38.060 回答