简体   繁体   English

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

[英]Derived method stronger than override in c#?

( again annoying question... ) 再次烦人的问题......

after asking this before - ( which is partly related to my question) - i got an answer : 之前问过这个 - (这部分与我的问题有关) - 我得到了一个答案:

See §7.6.5.1 of the C# 4 spec: 参见C#4规范的§7.6.5.1:

The set of candidate methods is reduced to contain only methods from the most derived types: For each method CF in the set, where C is the type in which the method F is declared, all methods declared in a base type of C are removed from the set. 候选方法集合被简化为仅包含来自大多数派生类型的方法:对于集合中的每个方法CF,其中C是声明方法F的类型,所有在基本类型C中声明的方法都从集合。

ok. 好。

i have this code : // .Dump() is like a WriteLine command... 我有这个代码: .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();}
    }

but this code : 但是这段代码:

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

emits : "1" 发出: "1"

but wait ... 可是等等 ...

didnt we say that is reduced to contain only methods from the most derived types: ? 我们不是说is reduced to contain only methods from the most derived types:

Child has 1 function from its father public void Foo(string strings) and a NEARER override function . Child从其父public void Foo(string strings)NEARER覆盖函数中有1个函数

so why did he choose its base's function ? 那他为什么选择它的基地功能呢? does the inherited function is CLOSER than the override ? 继承的函数是否比覆盖更复杂?

is it related to the fact that override is at runtime ? 是否与覆盖在运行时有关?

help please. 请帮助。

edit 编辑

what about this situation ? 这种情况怎么样?

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"
}

That's because your child takes an object. 那是因为你的孩子拿走了一个物体。

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

Make it string and then child one will be called. 使它成为字符串,然后将调用其中一个。

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

Why this? 为什么这个?

Because compiler sees that child has object prameter it has to convert to string while in base class it is readily available as string. 因为编译器看到子进程有object所以它必须转换为string而在基类中它可以作为字符串使用。

So it calls base one. 所以它称之为基础。

Though Overridden function is nearer in the child class. 虽然重写功能在子类中更接近。 But here rules are different in child and base. 但是这里的规则在孩子和基础上是不同的。 Child has object and base has string. 孩子有对象,基础有字符串。 It was fair if both had object or both had string. 如果两者都有object或者两者都有string.这是公平的string.

I read this in Jon Skeet's C# in Depth Overloading Section 我在Jon Skeet的深度超载部分C#中读到了这个

There are two concepts here which are being confused, overloading and overriding. 这里有两个概念混淆,重载和覆盖。 Overloading is the concept of having multiple signatures for a function of the same name and choosing one to call based on that signature . 重载是为同名函数提供多个签名并根据该签名选择一个进行调用的概念 Overriding is the concept of re-defining a method in a derived class. 覆盖是在派生类中重新定义方法的概念。

Whether or not the child class overrode one of the method definitions does not matter at all to which function will be called because it does not change the signature of either method. 子类是否覆盖其中一个方法定义与调用哪个函数完全无关,因为它不会更改任一方法的签名。 By definition and construction overriding a method cannot change it's signature . 根据定义和构造覆盖方法不能改变它的签名

So, if the signature is unchanged exactly the same mechanics for determining the correct function to call based on the signature will be used against both the parent and child classes. 因此,如果签名未更改,则基于签名确定正确调用函数的相同机制将用于父类和子类。

Update 更新

In fact there is a little bit more to it as Eric Lippert points out in his blog . 事实上,Eric Lippert在他的博客中指出,它还有一点点。 It turns out in fact that if there is a method that matches the overload in the child class it will not look for any methods in base classes. 事实证明,如果有一个方法匹配子类中的重载 ,它将不会在基类中查找任何方法。 The reasons are sane - avoiding breaking changes - but the result is somewhat illogical when you own both the base and child class. 原因是理智的 - 避免破坏变化 - 但是当你拥有基础和子类时,结果有点不合逻辑。

I can only echo Jon Skeet: "Given this oddness, my advice would be to avoid overloading across inheritance boundaries... at least with methods where more than one method could be applicable for a given call if you flattened the hierarchy" 我只能回应Jon Skeet:“鉴于这种奇怪,我的建议是避免跨越继承边界的重载......至少对于如果平铺层次结构,多个方法可适用于给定调用的方法”

You see here best match rule . 你看这里最好的比赛规则

You pass a string like an argument to a Foo(..) function. 您将类似参数的string传递给Foo(..)函数。

Base class has a Foo(string..) , Child class, instead, has not . 基类有一个Foo(string..) ,而Child类则没有 So the method of base is picked eventually , in this case. 因此,在这种情况下,最终选择基本方法。

I think here the base class method is chosen based on its dataType 我认为基于它的dataType选择了基类方法

As c.Foo("d"); 作为c.Foo("d"); matches exactly to the base class method and there is not any method overridden for it in the derived class therefore the base class method is called. 与基类方法完全匹配,并且在derived class没有为它重写任何方法,因此调用基类方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM