派生方法比c#中的覆盖更强?

时间:2012-05-28 07:28:30

标签: c# .net .net-4.0 clr

又烦人的问题......

之前询问 this 之后 - (这部分与我的问题有关) - 我得到了答案:

  

参见C#4规范的第7.6.5.1节:

     

将候选方法集合简化为仅包含来自的方法   派生类型最多:对于集合中的每个方法C.F,其中C是   声明方法F的类型,在基类中声明的所有方法   从集合中删除C的类型。

确定。

我有这个代码:// .Dump() is like a WriteLine command...

 public class Base
    {
        public void Foo(string strings)  { "1".Dump();}
        public virtual void  Foo(object strings)  { "2".Dump();}
    }

    public class Child : Base
    {

        public override void  Foo(object strings)  { "4".Dump();}
    }

但是这段代码:

Child c = new Child();
c.Foo("d");

发出:"1"

但等等......

我们不是说is reduced to contain only methods from the most derived types:

Child的父亲public void Foo(string strings)有一项功能, NEARER覆盖功能

那他为什么选择基地的功能呢?继承的函数是否比覆盖更隐蔽?

是否与覆盖在运行时有关?

请帮忙。

修改

这种情况怎么样?

public class Base
    {    
        public virtual void  Foo(int x)  { "1".Dump();}
    }

    public class Child : Base
    {
        public override void  Foo(int x)  { "2".Dump();}
        public void Foo(object x) { "3".Dump();}    
    }

void Main()
{
    Child c = new Child();
    c.Foo(6); //emits "3"
}

4 个答案:

答案 0 :(得分:6)

那是因为你的孩子拿走了一个物体。

public class Child : Base
{
    public override void Foo(object strings)  { "4".Dump();}
}

将其设为字符串,然后调用其中一个。

public class Child : Base
{
    public override void Foo(string strings)  { "4".Dump();}
}

为什么会这样?

因为编译器看到孩子有object参数,所以它必须转换为string,而在基类中,它可以作为字符串使用。

所以它称之为基础。

尽管子类中的重写函数更接近。但是这里的规则在孩子和基础上是不同的。孩子有对象,基础有字符串。如果两者都有object或两者都有string.

,那就太公平了

我在Jon Skeet的C# in Depth Overloading Section

中读到了这个

答案 1 :(得分:3)

这里有两个概念混淆,重载和覆盖。重载是为同名函数设置多个签名并选择一个根据该签名调用 的概念。覆盖是在派生类中重新定义方法的概念。

子类是否覆盖其中一个方法定义与调用哪个函数完全无关,因为它不会更改任一方法的签名。根据定义和构造覆盖方法不能改变它的签名

因此,如果签名没有改变,那么根据签名确定正确调用函数的相同机制将用于父类和子类。

<强>更新

事实上,正如Eric Lippert在his blog中所指出的那样,还有更多内容。事实证明,如果有一个方法匹配子类中的重载,它将不会在基类中查找任何方法。原因是理智的 - 避免破坏变化 - 但是当你拥有基础和子类时,结果有点不合逻辑。

我只能回应Jon Skeet:“鉴于这种奇怪,我的建议是避免跨越继承边界的重载......至少对于如果平铺层次结构,多个方法可适用于给定调用的方法”

答案 2 :(得分:1)

您在此处看到最佳匹配规则

您将string类似参数传递给Foo(..)函数。

基类有Foo(string..),而Child类则。所以最终选择了base的方法,在 this case中。

答案 3 :(得分:1)

我认为基类方法是根据dataType

选择的

由于c.Foo("d");与基类方法完全匹配,并且在derived class中没有为它重写任何方法,因此调用基类方法。