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

时间:2012-04-02 17:57:11

标签: c# override overloading

我有以下简单代码

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);
    }
}

当我运行此代码时,测试行((Int32)1)会因无限递归而导致堆栈溢出。正确调用正确方法(使用整数参数)的唯一可行方法是

(this as A).Test(1);

但这不适合我,因为两种方法测试都是公开的,我愿意用户能够调用这两种方法吗?

2 个答案:

答案 0 :(得分:5)

C#中的方法重载解析并不总是像您期望的那样,但是您的代码的行为符合规范(我之前写过a blog post)。

简而言之,编译器从找到

的方法开始
  • 具有相同的名称(在您的情况下为Test
  • 在类型(在您的情况下为B)或其基本类型之一
  • 中声明
  • 未使用覆盖修饰符
  • 声明

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

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

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

答案 1 :(得分:4)

不幸的是,为了通过A::Test(int)引用来调用B,需要进行某种强制转换。只要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
  }
}