当传递一个方法组作为参数时,为什么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)

当传递一个方法组作为参数时,为什么c#编译器不解析委托类型只在返回类型上不同?

因为这两个委托都可以在没有任何参数的情况下调用:

Action action = new Action(() => ...);
Func<bool> func = new Func<bool>(() => true);
action();
func(); // Legal even if you ignore the return value

在解决重载时不考虑返回类型

相关文章: