gpt4 book ai didi

c# - 使用多个重载和默认参数调用特定的基方法

转载 作者:行者123 更新时间:2023-11-30 15:51:53 25 4
gpt4 key购买 nike

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

首先,我们有一个基类 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(返回为“B 类函数 3 par”),但我想调用 C 中定义的 Foo(将返回“C 类函数 1 par”)。我认为这种使用默认参数重载虚函数会导致编译器出现不明确的错误,但它编译得很好。

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

最佳答案

这是可选参数与语言其余部分之间的不幸交互,也是您基本上永远不应该重载使用可选参数的方法(或向不使用可选参数的方法添加重载)的一个很好的理由。 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),因为方法组的委托(delegate)转换不考虑可选参数,因此 B.Foo(int, int, int) 不是有效的候选者,迫使我们进一步向上移动并找到 A.Foo(int)

关于c# - 使用多个重载和默认参数调用特定的基方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55798789/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com