【问题标题】:Method Inference does not work with method group方法推断不适用于方法组
【发布时间】:2011-12-06 10:44:13
【问题描述】:

考虑

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错误的描述是

以下方法或属性之间的调用不明确: 'System.Linq.Enumerable.Sum<string>(System.Collections.Generic.IEnumerable<string>, System.Func<string,decimal>)''System.Linq.Enumerable.Sum<string>(System.Collections.Generic.IEnumerable<string>, System.Func<string,decimal?>)'

我不明白的是,s =&gt; GetValue(s) 为编译器提供了哪些信息,而只是 GetValue 没有 - 后者不是前者的语法糖吗?

【问题讨论】:

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


    【解决方案1】:

    s =&gt; GetValue(s) 是一个 lambda 表达式,GetValue 是一个方法组,这是完全不同的东西。它们都可以被认为是 new Func&lt;string,double&gt;(...) 的语法糖,但它们相互关联的唯一方式是 lambda 表达式包含对 GetValue() 的调用。在转换为委托时,方法组在返回类型方面与 lambda 表达式具有不同的转换规则。请参阅Why is Func<T> ambiguous with Func<IEnumerable<T>>?Overloaded method-group argument confuses overload resolution?

    【讨论】:

      【解决方案2】:

      马克的回答是正确的,但可以使用更多的解释。

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

      具体来说,细微的差别在于仅根据 参数 是否匹配,而不是根据返回类型 匹配。 Lambda 检查参数和返回类型。

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

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

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

      【讨论】:

      • 如果你有一台时光机,你会如何改变它们?你会让他们考虑返回类型,比如 lambdas 吗?或者你会做出不同的细微改变?
      • 有趣!我在 LinqPad 中玩过它,事实上,即使我有 double D1(string s)int D1(string s),签名为 string M(string) 的方法组也会产生一个模棱两可的调用错误——即使两个签名都不适合。这与 lambda 不同,它会尝试所有这些,并在它尝试的最后一个(第一个?)给你一个转换错误。
      • 但是,如果没有重载解决问题(并且使用了错误的签名),方法组错误(“M 有错误的返回类型”)比 lambda 的(“Cannot将类型'string'隐式转换为'double'")
      猜你喜欢
      • 2014-09-07
      • 2021-07-04
      • 1970-01-01
      • 1970-01-01
      • 2023-02-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多