C#中的方法隐藏如何工作? (第二部分) [英] How method hiding works in C#? (Part Two)

查看:161
本文介绍了C#中的方法隐藏如何工作? (第二部分)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下程序打印

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆