【问题标题】:How to call overridden method which have overloads?如何调用具有重载的重写方法?
【发布时间】:2012-04-02 17:57:10
【问题描述】:

我有以下简单的代码

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

但这对我来说不合适,因为两个方法 Test 都是公开的,我愿意用户能够调用这两个方法?

【问题讨论】:

    标签: c# overriding overloading


    【解决方案1】:

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

    简而言之,编译器从查找方法开始

    • 同名(在您的情况下为Test
    • 在类型(在您的情况下为 B)或其基类型之一中声明
    • 未使用覆盖修饰符声明

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

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

    如果你想调用你被覆盖的方法,你需要先把对象转换成它的基类型。

    【讨论】:

      【解决方案2】:

      不幸的是,为了通过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
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-18
        相关资源
        最近更新 更多