无法使用表达式初始化LambdaExpression

时间:2011-08-10 20:36:01

标签: c# lambda expression-trees

类似于one by 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。被强制在每个方法调用上显式地将lambdas强制转换为相应的Expression<Func<T1,T2>>令人沮丧。

在这种情况下,为什么会破坏这种基本的OOP行为?

3 个答案:

答案 0 :(得分:8)

转换不起作用,因为编译器无法推断您尝试创建的特定表达式类型。如果你这样做会怎么样?

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,还是其他一些无争议的无效回归代表?

答案 1 :(得分:0)

写作时

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

答案 2 :(得分:0)

C#编译器将表达式计算为最不复杂的形式,例如:

 var x = (object o) => new object();

x应该是Func<object, object>,而不是Expression<Func<object, object>>。在这种情况下,编译器确定值是委托,并且由于Expression不能接受委托(只有Expression<Func<>> / Expression<Action>类型可以),因此抛出编译器错误。

另外,请参阅@Riana的答案,因为表达式是由编译器重写的。