如何调用具有重载的重写方法

本文关键字:重载 重写 方法 何调用 调用 | 更新日期: 2023-09-27 18:29:42

我有下面的简单代码

abstract class A
{
    public abstract void Test(Int32 value);
}
class B : A
{
    public override void Test(Int32 value)
    {
        Console.WriteLine("Int32");
    }
    public void Test(Double value)
    {
        Test((Int32)1);
    }
}

当我运行此代码时,Test((Int32)1)行由于无限递归而导致堆栈溢出。我找到的唯一可能正确调用正确方法(带整数参数)的方法是

(this as A).Test(1);

但这对我来说并不合适,因为测试的两个方法都是公共的,我希望用户能够调用这两个方法?

如何调用具有重载的重写方法

C#中的方法重载解析并不总是像您预期的那样运行,但您的代码是按照规范运行的(我不久前写了一篇关于这方面的博客文章)。

简而言之,编译器从找到

  • 具有相同的名称(在您的情况下为Test
  • 在类型(在您的情况下为B)或其基类型之一中声明
  • 未使用重写修饰符声明

请注意最后一点。这实际上是合乎逻辑的,因为虚拟方法是在运行时解析的,而不是在编译时解析的。

最后,如果类型(在本例中为B)有一个候选方法(这意味着调用中的参数可以隐式转换为候选方法的参数类型),则将使用该方法。您被覆盖的方法甚至不是决策过程的一部分。

如果要调用重写的方法,则需要首先将对象强制转换为其基类型。

不幸的是,为了通过B引用调用A::Test(int),需要某种类型的强制转换。只要C#编译器通过B看到引用,它就会选择B::Test(double)版本。

一个稍微不那么难看的版本是下面的

((A)this).Test(1);

不过,另一个想法是使用一个不同名称的私有方法,这两个方法都可以输入。

class B : A { 
  public override void Test(int i) {
    TestCore(i);
  }
  public void Test(double d) {
    TestCore(1);
  }
  private void TestCore(int i) {
    // Combined logic here
  }
}