(又烦人的问题...... )
之前询问 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"
}
答案 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
中没有为它重写任何方法,因此调用基类方法。