不能用表达式初始化LambdaExpression
本文关键字:LambdaExpression 初始化 表达式 不能 | 更新日期: 2023-09-27 18:05:03
类似John K的问题,但更具体,公认的答案不适合我的需要。
这个编译得很好:
Expression<Func<object, object>> specificExpression = (object o) => new object();
Expression generalExpression = specificExpression;
这个没有
Expression generalExpression = (object o) => new object();
报告编译错误:
Cannot convert lambda expression to type 'System.Linq.Expressions.Expression' because it is not a delegate type
Expression<Func<T1,T2>>
来源于Expression
。
现在我有一个框架的方法接受各种表达式,即类型Expression
。被迫在每个方法调用时显式地将lambda转换为相应的Expression<Func<T1,T2>>
是令人沮丧的。
在这种情况下,有什么好的理由可以解释为什么这个基本的OOP行为被破坏了吗?
转换不起作用,因为编译器无法推断您要创建的特定表达式类型。如果是你做的呢?
Expression generalExpression = (object o) => "foo";
应该是Expression<Func<object, string>>
吗?那Expression<Func<object, object>>
和Expression<Func<object, IComparable>>
呢?这些类型都是表达式树的有效最终类型,编译器不会假装知道您要做什么。
你需要通过特定的类型强制转换来通知编译器你想生成哪种类型的表达式:
Expression generalExpression = (Expression<Func<object, object>>)
(object o) => new object();
你会看到一个类似的编译错误,如果你尝试:
Delegate generalDelegate = delegate() { };
是一个Action
,或ThreadStart
,或其他类型的无参数无效返回委托?
当你写
Expression<Func<object, object>> specificExpression = (object o) => new object();
这实际上是c#编译器为我们提供的一种方便的编写。
这个表达式实际上会被编译成这样:
Expression.Lambda<Func<object, object>> specificExpression = Expression.Lambda<Func<object,object>> ( ... )
,正如你所看到的,Expression<Func<object,object>>
不是一个委托类型,即使第一个表达式可能会导致错误,让我们相信情况就是这样。
"Expression"不是委托类型,所以你不能直接给它赋值一个委托对象,因为编译器不提供编写的便利(像Expression<T>
类那样)。
很抱歉这么说,但你不得不走那条令人沮丧的路。
Riana
c#编译器将表达式求值为最简单的形式,例如:
var x = (object o) => new object();
x
应该是Func<object, object>
,而不是Expression<Func<object, object>>
。在这种情况下,编译器确定该值是委托,并且由于Expression
不能接受委托(只有Expression<Func<>>
/Expression<Action>
类型可以),因此会抛出编译器错误。
还有,看@Riana的回答,因为表达式形式实际上是由编译器重写的。