Pra*_*ter 13 c# compiler-construction inheritance method-hiding
打印以下程序
A:C(A,B)
B:C(A,B)
Run Code Online (Sandbox Code Playgroud)
(正如它应该)
public interface I
{
string A();
}
public class C : I
{
public string A()
{
return "A";
}
public string B()
{
return "B";
}
}
public class A
{
public virtual void Print(C c)
{
Console.WriteLine("A:C(" + c.A() + "," + c.B() + ")");
}
}
public class B : A
{
public new void Print(C c)
{
Console.WriteLine("B:C(" + c.A() + "," + c.B() + ")");
}
public void Print(I i)
{
Console.WriteLine("B:I(" + i.A() + ")");
}
}
class Program
{
public static void Main(string[] args)
{
A a = new A();
B b = new B();
C c = new C();
a.Print(c);
b.Print(c);
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我在B类中将关键字'new'更改为'override',如下所示:
public override void Print(C c)
Run Code Online (Sandbox Code Playgroud)
突然之间的程序开始打印:
A:C(A,B)
B:I(A)
Run Code Online (Sandbox Code Playgroud)
为什么?
这与如何解决重载方法有关.
有效地(稍微简化),编译器首先查看表达式(B)的声明类型,并查找首先在该类型中声明的候选方法.如果有任何适当的方法(即所有参数都可以转换为方法的参数类型),那么它不会查看任何父类型.这意味着如果在派生类型中存在任何"新近声明的"适当方法,则初始声明在父类型中的重写方法不会获得查找.
这是一个稍微简单的例子:
using System;
class Base
{
public virtual void Foo(int x)
{
Console.WriteLine("Base.Foo(int)");
}
}
class Derived : Base
{
public override void Foo(int x)
{
Console.WriteLine("Derived.Foo(int)");
}
public void Foo(double d)
{
Console.WriteLine("Derived.Foo(double)");
}
}
class Test
{
static void Main()
{
Derived d = new Derived();
d.Foo(10);
}
}
Run Code Online (Sandbox Code Playgroud)
这版画Derived.Foo(double)-即使编译器知道有型的参数的匹配方法int,和参数的类型int,并将其从转换int到int从比转换"更好" int来double,只有事实Foo(double)的方法最初宣布在Derived表示编译器忽略Foo(int).
这是非常令人惊讶的IMO.我可以看到为什么它会是如果案件Derived没有重载Foo-否则将在基类一个新的,更具体的,方法可能会意外更改的行为-但显然Derived这里知道有关Base.Foo(int),因为它的覆盖它.这是(相对较少)的一点,我认为C#设计师做出了错误的决定.