【问题标题】:Methods priority new vs override wrong [duplicate]方法优先级新与覆盖错误[重复]
【发布时间】:2019-09-23 09:24:16
【问题描述】:

我在这样描述的类中遇到了意外(对我来说出乎意料)的方法调用:

class Program
{
    static void Main(string[] args)
    {
        int param = 5;
        var item = new Derived();
        item.DoWork(param);
        Console.ReadLine();
    }
}

class Derived : Base
{
    public override void DoWork(int param) { Console.WriteLine("derived int"); }

    public new void DoWork(double param) { Console.WriteLine("derived double"); }
}

class Base
{
    public virtual void DoWork(int param) { Console.WriteLine("base int"); }

    public virtual void DoWork(double param) { Console.WriteLine("base double"); }
}

我希望输出是:"derived int",但奇怪的是"derived double"。如果我将new 关键字更改为override,那么我会看到预期的输出"derived int"。似乎我错过了与继承逻辑相关的内容。
有人可以解释这种行为吗?

【问题讨论】:

  • 看看这个thread和John Skeet的解释
  • “new”修饰符指示编译器使用您的子类实现而不是父类实现。任何不引用您的类但父类的代码都将使用父类实现。因此,当您使用“新”时,您是在说使用该实现。看到这个thread
  • @PavelAnikhouski,那为什么不投票给重复,这是合适的,看到新的只是表明从开发人员的角度来看不覆盖原始方法是为了编译器(结果过于复杂)

标签: c#


【解决方案1】:

这不是继承问题,而是overload 问题。 以下是编译器如何解决重载的方法调用:

  1. 首先,编译器查看派生最多的类型
  2. 编译器仅将那些类型推断成功但未在基类中声明的方法添加到候选方法池中(因此override 方法不会添加到池中,而新声明的方法是)
  3. 如果池中没有可供选择的候选者,编译器会查看当前类型的基类型并返回步骤 2。如果当前类型没有基类型,则会发生编译时错误李>
  4. 如果方法池中至少有一个有效的候选方法,编译器会使用其重载解析规则选择要调用的方法
  5. 如果从第 4 步中可以识别出多个用于调用的方法,则会发生编译时错误

在这种情况下,在从派生类调用 DoWork 之后,在第 2 步中,编译器仅将标记为 new 的方法添加到池中。 另一方面,如果你从基类调用方法,如下所示,你会得到你期望的输出:

int param = 5;
Base item = new Derived();
item.DoWork(param);

// output: derived int

Source

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2012-12-14
    • 2010-12-07
    • 2018-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多