将Lambda表达式转换为委托实例还是表达式树?

4
在阅读了相关的答案后,我仍有一个问题:
Lambda表达式是代替委托实例而编写的未命名方法。编译器会立即将lambda表达式转换为以下两者之一:
  • 委托实例。
  • 类型为Expression的表达式树,表示可遍历对象模型中lambda表达式内部的代码。
但是,什么时候会将其转换为委托实例,什么时候会将其转换为表达式树呢?(没有找到相关信息)
并没有太多相关的代码-只是试着玩玩-显然两者都匹配。我没想到这样因为我认为其中一个会更匹配。
void Main()
{
     Foo( () => 0 );
}
  void Foo(Func<int > action)
{
    Console.WriteLine("1");
}

  void Foo(Expression<Func<int>> func)
{
    Console.WriteLine("2");
}

这将导致错误(以下方法或属性之间存在歧义)

不确定我是否理解。如果您使用自己的委托,比如 delegate int Blah(),并且有 void Foo(Blah blah),情况也是一样的。 - leppie
@leppie 这段代码是从Jon在链接中写的,我试着对它进行了一些修改。我只是想知道是什么让编译器将其转换为委托实例而不是表达式树。 - Royi Namir
2
它将转换为您已经有效要求的任何形式。您的代码是不明确的,因为它可以转换为 Func<int>Expression<Func<int>>,而且没有一种转换被认为是“更好”的。不清楚您在询问什么。 - Jon Skeet
@JonSkeet,您是在说上下文是编译器决定的因素吗?例如,linq-2-sql会将其转换为表达式树...? - Royi Namir
个人而言,我甚至不会费心处理这种重载。只需给它一个不同的名称,问题就解决了;p - leppie
显示剩余3条评论
1个回答

5
它会转换成您所要求的任何类型。例如:
Func<int> del = () => 0; // Conversion to delegate
Expression<Func<int>> expression = () => 0; // Conversion to expression tree

在您的情况下,由于函数重载,您要求编译器同时考虑两种形式的转换。如果移除Foo(Expression<Func<int>> func)方法,则代码将有效,并且编译器会将lambda表达式转换为委托。如果相反地移除另一个方法,则代码将有效,并且编译器会将lambda表达式转换为表达式树。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接