【问题标题】:Lambda conversions with unclear return type and overload resolution [duplicate]具有不明确的返回类型和重载分辨率的 Lambda 转换 [重复]
【发布时间】:2012-08-13 20:27:03
【问题描述】:

如果我有一个 lambda,例如 () => { throw new Exception(); },则不清楚它是否有返回类型。因此,它可以(隐式)转换为ActionFunc<object>(或任何其他Func<T>)。这是因为,根据 C# 4 规范的 §6.5 匿名函数转换

[A] 委托类型D 与提供的匿名函数F 兼容:

  • 如果D 有一个void 返回类型并且F 的主体是一个语句块,那么当[...] F 的主体是一个有效的语句块,其中没有返回语句指定一个表达式。

  • 如果D 有一个非空返回类型并且F 的主体是一个语句块,当[...] F 的主体是一个有效的语句块时,它的端点不可到达每个return 语句都指定一个表达式,该表达式可以隐式转换为D 的返回类型。

但是,如果我有一个方法的两个重载,其中一个具有 Action 类型的参数,另一个具有 Func<object> 类型的参数,并且我从上面传递 lambda,则使用 Func<object> 重载。为什么?在这种情况下,规范的哪一部分说Func<object> 优于Action

我看过 §7.5.3.2 更好的函数成员,但这并没有解释它。

【问题讨论】:

  • 如果您使用符号 delegate { throw new Exception(); } 代替 lambda 语法,在 () 括号中省略参数列表,则该匿名函数可以匹配 any 委托我猜的签名,也包括例如EventHandlerAction<object, EventArgs>.
  • @JeppeStigNielsen 是的。在这种情况下,确实没有规则可以将它们作为方法参数来消除歧义,所以你会得到一个编译错误。

标签: c# lambda overload-resolution


【解决方案1】:

我应该往下看一节:§7.5.3.3 更好地从表达式转换解释说:

给定一个隐式转换 C<sub>1</sub> 从表达式 E 转换为类型 T<sub>1</sub>,以及一个隐式转换 C<sub>2</sub> 从表达式 E 转换为类型 T<sub>2</sub>, C<sub>1</sub>如果以下至少一项成立,则比 C<sub>2</sub> 更好的转换:

  • E 是匿名函数,T<sub>1</sub> 是委托类型D<sub>1</sub> 或表达式树类型Expression&lt;D<sub>1</sub>&gt;T<sub>2</sub> 是委托类型D<sub>2</sub> 或表达式树类型Expression&lt;D<sub>2</sub>&gt;并满足以下条件之一:

    • D<sub>1</sub>D<sub>2</sub> 具有相同的参数列表,并且满足以下条件之一:

      • D<sub>1</sub> 有一个返回类型Y,而D<sub>2</sub> 是无效返回

【讨论】:

  • 您在提出问题的同时发布了这个答案?
  • 是的,当我写这个问题时,我注意到了规范中的答案。所以我不想浪费任何人的时间来研究这个。但与此同时,我认为它可能对其他人有用。
  • 这个答案解释了观察到的行为如何符合规范,但它没有(也不能)解释为什么规范首先是这样编写的。幸运的是,在编译器中实现该功能的人we now have word 也解释了这一点!
猜你喜欢
  • 2016-04-02
  • 2014-01-09
  • 2014-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多