c# - 方法推断不适用于方法组

标签 c# .net-4.0 type-inference method-group

考虑

void Main()
{
    var list = new[] {"1", "2", "3"};
    list.Sum(GetValue); //error CS0121
    list.Sum(s => GetValue(s)); //works !
}

double GetValue(string s)
{
    double val;
    double.TryParse(s, out val);
    return val;
}

CS0121错误的描述是

The call is ambiguous between the following methods or properties: 'System.Linq.Enumerable.Sum<string>(System.Collections.Generic.IEnumerable<string>, System.Func<string,decimal>)' and 'System.Linq.Enumerable.Sum<string>(System.Collections.Generic.IEnumerable<string>, System.Func<string,decimal?>)'

我不明白的是,s => GetValue(s)是什么信息?给编译器简单的 GetValue不是 - 后者不是前者的语法糖吗?

最佳答案

Mark 的回答是正确的,但需要更多解释。

问题确实是由于方法组的处理方式与 lambda 的处理方式之间存在细微差别。

具体来说,细微差别在于方法组被认为可转换为委托(delegate)类型仅基于参数是否匹配,而不是基于是否匹配返回类型匹配。Lambda 会同时检查参数和返回类型。

这个奇怪规则的原因是方法组转换为委托(delegate)本质上是重载决议问题的解决方案。假设 D 是委托(delegate)类型 double D(string s),M 是一个方法组,其中包含一个接受字符串并返回字符串的方法。在解析从 M 到 D 的转换的含义时,我们会像您说的是 M(string) 一样进行重载解析。重载解析会选择接受一个字符串并返回一个字符串的 M,因此 M 可以转换为该委托(delegate)类型即使转换稍后会导致错误。正如如果您说“string s = M(null);”,“常规”重载解析会成功一样。 -- 重载解析成功,即使稍后导致转换失败。

这个规则很微妙而且有点奇怪。它的结果是您的方法组可以转换为所有不同的委托(delegate)类型,它们是每个采用委托(delegate)的 Sum 版本的第二个参数。由于找不到最佳转换,方法组 Sum 的重载决策是不明确的。

方法组转换规则看似合理,但在 C# 中有点奇怪。我有点恼火,因为它们与更“直观正确”的 lambda 转换不一致。

关于c# - 方法推断不适用于方法组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24677748/

相关文章:

c# - C++/CLI 中是否有等效于 C# "var"关键字的关键字?

scala - 重载函数导致 "missing parameter type for expanded function"错误

c# - 在 C# 中使用 pinvoke 时 [In, Out] 和 ref 有什么区别?

.net - 帮助我了解休眠线程的性能和行为

c# - 如何在 C# 类库中使用 Ninject

c# - AZMan:InitializeClientContextFromName 失败,返回 "Value does not fall within the expected range."

scala - 隐式搜索不指导类型推断在 Scala 中查找父类(super class)型

Scala:如何定义 "generic"函数参数?

c# - 为 WPF 标题添加事件处理程序

c# - 在 C# 中杀死除我的程序之外的所有进程