5

为什么 expr1 可以编译,而 expr2 不能编译?

Func<object> func = () => new object();
Expression<Func<object>> expr1 = () => new object();
Expression<Func<object>> expr2 = func; //Cannot implicitly convert type 'System.Func<object>' to 'System.Linq.Expressions.Expression<System.Func<object>>'
4

4 回答 4

4

AFunc<T>是委托(指向函数的指针),而 anExpression<Func<T>>是表达式树(描述操作的树状数据结构)。因此,您不能将一个分配给另一个,因为它们完全不同。

当您将 lambda 函数直接分配给 a 时Func<T>,编译器会为您的函数编译代码并将指向已编译代码的指针分配给 eg func

另一方面,当您将 lambda 函数直接分配给 a 时Expression<Func<T>>,编译器会构建表达式树(它只是引用类型的一个实例)并将对该对象的引用分配给 eg expr1。这只是编译器为您提供的一种便利,为您提供了一个比自己在代码中手动构建表达式树更具吸引力的选择(当然这也是完全可能的)。

于 2013-01-12T21:01:15.797 回答
3

您不能在FuncExpression类型之间进行转换。但是您可以从 lambda 转换为其中任何一个。

lambda 具有仅存在于 C# 类型系统中的特殊类型。CLR 不知道什么是 lambda。只有 C# 编译器知道这一点,并且您可以对 lambda 执行的唯一操作是转换为FuncandExpression类型。(这意味着您不能调用 lambda,例如,因为它根本没有 CLR 类型)。

这就是为什么您在这里观察到“语义鸿沟”的原因。

于 2013-01-12T21:18:09.507 回答
2

简而言之,编译器可以将一段代码(Lambda表达式)转换为

  • 一个Expression
  • 一个Func

这在使用时立即发生,然后代码消失,转换为不可逆。但是FuncExpression是完全不同的类型。

这就是为什么你不能

Expression<Func<object>> expr2 = func;

但反过来也可以

Func<object> func2 = expr1.Compile();
于 2013-01-12T22:35:17.297 回答
0

因为System.Func<object>System.Linq.Expressions.Expression<System.Func<object>>是不同的类型。您不能隐式转换它们。

Func<T>是代表。从 看MSDN

封装没有参数的方法,并返回由 T 参数指定的类型的值。

Expression<Func<T>>是一个表达式树。

于 2013-01-12T21:01:58.740 回答