当传递一个方法组作为参数时,为什么c#编译器不解析委托类型只在返回类型上不同?
本文关键字:编译器 类型 返回类型 为什么 一个 方法 参数 | 更新日期: 2023-09-27 18:16:54
请考虑以下代码:
class Program
{
static void Foobar() { }
static void Test(Action a) { }
static void Test(Func<bool> a) { }
static void Main(string[] args)
{
Test(Foobar);
}
}
它不能在VS2012上编译。编译器抱怨说,Test(Foobar)
行中对方法Foobar的引用有歧义。这是我得到的全部错误信息:
The call is ambiguous between the following methods or properties:
'Program.Test(System.Action)' and 'Program.Test(System.Func<bool>)'
现在,修复将只是将Foobar转换为一个Action来强制正确的重载:Test((Action)Foobar)
.
但是我对原因很感兴趣,为什么c#不能自己解决这个问题?为什么他必须认为Func<bool>
是void()
函数的有效过载?
我知道你不能用另一个方法重载一个方法,只是返回类型不同。但这里的情况似乎并非如此。我没有超载Foobar()
。当然,返回值可能不是Foobar签名的一部分,但是当涉及到从方法组到委托的转换时,为什么这很重要?
我也意识到这个问题,编译器有时拒绝将带有重载方法的方法组强制转换为特定的委托,即使他可以拥有他需要的所有信息,但我认为这是一个不同的问题(和不同的错误消息)。Foobar没有超载。只有Test()
是。
编辑:正如Matthew指出的,这个问题和链接的问题是一样的。然而,我对Eric Lippert和Jon Skeet给出的(非常好的)答案不是100%满意。
在他的回答的一部分,Eric说:
这里的原则是确定方法组可转换性需要选择a方法组中的方法使用重载解析,而则使用重载解析不考虑返回类型。
知道为什么吗?对我来说,似乎解决问题的方法正是改变上面的这句话,并在从方法组中选择方法时考虑返回类型。结束了,大家都很开心,不是吗?;)
为什么这个模棱两可的错误很糟糕的一个实际例子是,Task.Run()
不能在没有强制类型转换的自己类的void()
方法上使用。因此,即使在我看到的一些MSDN示例中,他们也使用Task.Run(() => Foobar())
而不是更干净的Task.Run(Foobar)
。
因为这两个委托都可以在没有任何参数的情况下调用:
Action action = new Action(() => ...);
Func<bool> func = new Func<bool>(() => true);
action();
func(); // Legal even if you ignore the return value
在解决重载时不考虑返回类型