gpt4 book ai didi

c# - 消除在重载调用中作为委托(delegate)传递的重载方法之间的歧义

转载 作者:太空狗 更新时间:2023-10-29 17:49:18 25 4
gpt4 key购买 nike

假设我在 C# 中有这个:

class OverloadTest
{
void Main()
{
CallWithDelegate(SomeOverloadedMethod);
}

delegate void SomeDelegateWithoutParameters();
delegate void SomeDelegateWithParameter(int n);

void CallWithDelegate(SomeDelegateWithoutParameters del) { }
void CallWithDelegate(SomeDelegateWithParameter del) { }

void SomeOverloadedMethod() { }
void SomeOverloadedMethod(int n) { }
}

当然,这不会编译,因为行 CallWithDelegate(SomeOverloadedMethod); 是不明确的。

现在,假设只有一个 CallWithDelegate(SomeDelegateWithoutParameter del) 函数(没有重载)。在这种情况下,不会有歧义,因为从似乎正在发生的事情来看,编译器可以查看参数类型并从候选列表中丢弃 SomeOverloadedMethod(int n)(因为它只能接受一个 SomeDelegateWithoutParameters),然后编译。

我不打算写这样的代码;从编译器编写者的角度来看,这只是出于好奇。我找不到关于这个的答案,因为很难用语言表达。

我想知道 C# 中是否有任何方法可以消除给定示例中 Main() 中的调用的歧义,以便它可以编译。您如何指定它,以便它解析为 CallWithDelegate(SomeDelegateWithoutParameters del) 被传递 SomeOverloadedMethod(),或 CallWithDelegate(SomeDelegateWithParameter del) 被传递SomeOverloadedMethod(int n)?

最佳答案

有几种方法可以消除方法组重载决议的歧义。

方法一:投方法组

CallWithDelegate((SomeDelegateWithoutParameters)SomeOverloadedMethod);
CallWithDelegate((SomeDelegateWithParameter)SomeOverloadedMethod);

这消除了重载的歧义。这是一种非常不常见的语法,但它有效(C# 5 规范 §6.6 方法组转换):

As with all other implicit and explicit conversions, the cast operator can be used to explicitly perform a method group conversion.

[...]

Method groups may influence overload resolution, and participate in type inference.

方法二:显式实例化委托(delegate)

CallWithDelegate(new SomeDelegateWithoutParameters(SomeOverloadedMethod));
CallWithDelegate(new SomeDelegateWithParameter(SomeOverloadedMethod));

这与之前没有语法糖的方法相同。有关更多详细信息,请参阅§7.6.10.5 委托(delegate)创建表达式中的规范。

The binding-time processing of a delegate-creation-expression of the form new D(E), where D is a delegate-type and E is an expression, consists of the following steps:

  • If E is a method group, the delegate creation expression is processed in the same way as a method group conversion (§6.6) from E to D.

[...]

甚至还有一个与您的问题密切相关的例子:

As described above, when a delegate is created from a method group, the formal parameter list and return type of the delegate determine which of the overloaded methods to select. In the example

delegate double DoubleFunc(double x);

class A
{
DoubleFunc f = new DoubleFunc(Square);
static float Square(float x) {
return x * x;
}
static double Square(double x) {
return x * x;
}
}

the A.f field is initialized with a delegate that refers to the second Square method because that method exactly matches the formal parameter list and return type of DoubleFunc. Had the second Square method not been present, a compile-time error would have occurred.

方法三:使用lambda

CallWithDelegate(() => SomeOverloadedMethod());
CallWithDelegate(i => SomeOverloadedMethod(i));
CallWithDelegate((int i) => SomeOverloadedMethod(i)); // Explicit types, if needed

这种形式没有歧义,但它具有间接性(调用 lambda,然后调用目标方法)。不过,这可能会被 JIT 优化,而且很可能不会对性能产生明显的影响。

方法四:使用匿名委托(delegate)

CallWithDelegate(delegate() { SomeOverloadedMethod(); });
CallWithDelegate(delegate(int i) { SomeOverloadedMethod(i); });

这等同于 lambda 调用,但它使用更庞大(和更旧)的 delegate 语法。


如果您想知道确切的重载决议规则,它们在§7.5.3 重载决议的规范中有描述。

关于c# - 消除在重载调用中作为委托(delegate)传递的重载方法之间的歧义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31866090/

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