类似于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行为?
答案 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的答案,因为表达式是由编译器重写的。