【问题标题】:Calling specific base method with multiple overloads and default parameters使用多个重载和默认参数调用特定的基本方法
【发布时间】:2019-09-11 21:43:52
【问题描述】:

我正在构建游戏的源代码,并尝试使用重载方法和默认参数调用基本虚拟函数。我无法更改派生的类,并且需要在我自己的虚方法类定义中调用该函数。我会尝试用代码更详细的解释。

首先,我们有一个基类 A,它定义了一个名为 Foo 的虚函数,它接受一个参数。

class A
{
   public virtual string Foo(int a)
   {
      return "Class A Function 1 par";
   }
}

然后是一个 B 类,它覆盖 Foo 并使用两个新的默认参数为 Foo 定义一个新的重载虚函数。

class B : A
{
   public virtual string Foo(int a, int b = 0, int c = 0)
   {
      return "Class B Function 3 par";
   }

   public override string Foo(int a)
   {
      return "Class B Function 1 par";
   }
}

然后是我需要派生的类,C。它只是覆盖了一个参数 Foo。

class C : B
{
   public override string Foo(int a)
   {
      return "Class C Function 1 par";
   }
}

最后是我的 D 类,它也覆盖了一个参数 Foo 但也需要能够调用 Foo 的基本方法。

class D : C
{
   public override string Foo(int a)
   {
      return base.Foo(0);
   }
}

这导致调用 B 中定义的三个参数 Foo(返回为“Class B Function 3 par”),但我想调用 C 中定义的 Foo(将返回“Class C Function 1 par”)。我认为这种带有默认参数的虚函数重载会导致一个模棱两可的编译器错误,但它编译得很好。

有没有办法解决这个问题,如果没有,为什么它允许类的结构阻止我访问基本方法?

【问题讨论】:

    标签: c# inheritance overriding overloading virtual


    【解决方案1】:

    这是可选参数与语言其余部分之间的不幸交互,也是您基本上不应该重载使用可选参数的方法(或向不使用可选参数的方法添加重载)的一个很好的理由。 B的作者做了一件非常糟糕的事情!

    调用没有歧义,因为base 的方法查找规则没有改变,只有在重载决议后最终调用的方法的规则 - 实际上,重载被确定为好像调用已阅读((C) this).Foo(0)。对于该调用,B.Foo(int, int, int) 被认为是唯一的候选者,因为它是沿继承链向上走时最接近的非override 方法——在我们考虑A.Foo(int) 之前就选择了它。如果A 引入了该方法,则不会有任何问题,因为在这种情况下,单参数重载会被认为是更好的方法。

    如果可选参数从一开始就是 C# 的一部分,而不是相对较晚的添加(在调用站点扩展值的一些古怪实现),这可能已经被考虑并以某种方式减轻了。因为它代表最明显的解决方法是通过实际更改base 查找的规则,因此它更喜欢匹配与它发生的方法的签名完全匹配的方法,但这只会使已经复杂的规则复杂化重载决议甚至更多,它肯定会破坏现有的代码,所以发生这种情况的可能性很小。

    如果您无法更改 ABC,仍然可以编写 D 来获得所需的行为,方法是利用(如果是这样的话)另一个相当晦涩的 C# 功能甚至更老:方法组!

    class D : C
    {
       public override string Foo(int a) 
       {
          Func<int, string> foo = base.Foo;
          return foo(a);
       }
    }    
    

    这明确地调用了C.Foo(int),因为方法组上的委托转换不考虑可选参数,因此B.Foo(int, int, int)不是一个有效的候选者,迫使我们更进一步地找到A.Foo(int)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      • 2015-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多