C#中的方法隐藏如何工作? (第二部分) [英] How method hiding works in C#? (Part Two)
问题描述
以下程序打印
A:C(A,B)
B:C(A,B)
(应该)
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);
}
}
然而,如果我将关键字'new'覆盖类B中的方法:
however, if I change keyword 'new' to 'override' in class B like so:
public override void Print(C c)
所有突然的程序开始打印:
all of a sudden program starts to print:
A:C(A,B)
B:I(A)
?
推荐答案
这是关于重载方法的解决方法。
This is to do with how overloaded methods are resolved.
有效地(在某种程度上简化),编译器首先在这种情况下查看表达式(B)的声明类型,并寻找首先在该类型中声明的候选方法。如果有任何适当的方法(即所有参数都可以转换为方法的参数类型),那么它不会看任何父类型。这意味着如果在派生类型中有任何新声明的适当的方法,那么重写的方法,其中初始声明是父类型的,不会被查找。
Effectively (simplified somewhat), the compiler first looks at the declared type of the expression (B) in this case and looks for candidate methods which are first declared in that type. If there are any methods which are appropriate (i.e. where all the arguments can be converted to the method's parameter types) then it doesn't look at any parent types. This means that overridden methods, where the initial declaration is in a parent type, don't get a look-in if there are any "freshly declared" appropriate methods in the derived type.
这里有一个更简单的例子:
Here's a slightly simpler example:
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);
}
}
打印 Derived.Foo (double)
- 尽管编译器知道有一个类型为 int
的参数的匹配方法,参数是 int
,并且从 int
到 int
的转换比从 int
到 double
的转换,只有 Foo(double)
方法最初在中声明 表示编译器忽略
Foo(int)
。
This prints Derived.Foo(double)
- even though the compiler knows there is a matching method with a parameter of type int
, and the argument is type int
, and the conversion from int
to int
is "better" than the conversion from int
to double
, the fact that only the Foo(double)
method is originally declared in Derived
means the compiler ignores Foo(int)
.
这是非常令人惊讶的IMO。我可以看到为什么如果 Derived
没有覆盖 Foo
,否则会引入一个新的,更具体的,基类中的方法可能会意外地改变行为 - 但是清楚地派生
这里知道关于 Base.Foo
,因为它正在覆盖它。这是(相对较少)点之一,我相信C#设计师做出错误的决定。
This is highly surprising IMO. I can see why it would be the case if Derived
didn't override Foo
- otherwise introducing a new, more specific, method in the base class could change the behaviour unexpectedly - but clearly Derived
here knows about Base.Foo(int)
as it's overriding it. This is one of the (relatively few) points where I believe the C# designers made the wrong decision.
这篇关于C#中的方法隐藏如何工作? (第二部分)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!