实际上,有四个相关的问题:
1)为什么可以这样做?
Expression<Func<int, int>> incrementorExpression = (i => i + 1);
但是无法做到这一点?
LambdaExpression decrementorExpression = (i => i - 1);
在第二种情况下,编译器将这样报告:“无法将lambda表达式转换为类型'System.Linq.Expressions.LambdaExpression',因为它不是委托类型”
2)之间的转换TDelegate
和Expression<TDelegate>
声明在哪里?我想我记得曾经看过它,但似乎现在找不到。但是我不确定我是否看过。
3)当我这样做时:
Expression<Func<int, int>> incrementExpression = (i => ++i);
编译器说:“表达式树可能不包含赋值运算符。” 为什么?
4)然后,如果我可以这样做:
Expression<Func<int, int>> incrementorExpression = (i => i + 1);
那么,为什么我不能做这个?
public Expression<Func<T>> ToExpression<T>(Func<T> func)
{
return func;
}
您几乎已经找到答案了。
i => i + 1
不是Func<int, int>
。这是一个lambda表达式。Lambda表达式可以转换为匹配的委托类型或匹配的表达式树类型。
如果将lambda表达式转换为委托类型,则编译器会将其编译为具有指定效果的IL代码。
如果将lambda表达式转换为表达式树类型,则编译器会将其编译为IL,IL生成一个表达式树,该树表示您在lambda表达式中编写的内容。表达式树是供库稍后进行解析的,因此,表达式树与您编写的代码紧密匹配非常重要。
Func<int, int> f = i => i + 1; // okay, creates delegate.
Expression<Func<int, int>> e = i => i + 1; // okay, creates expression tree.
无法从中获取f
有关其执行的操作的信息。从其委托类型可以知道,它接受int
并返回int
,但除此之外,它是一个黑盒。您输入数字,然后输入数字,但是您不再知道如何操作。
e
另一方面,存储事实,该事实1
已添加到名为的参数中i
,甚至1
出现在的RHS中+
。
e
对于那些解释表达式树的库来说,存储在其中的这些额外信息通常是必不可少的,因此从Func<int, int>
到的隐式转换Expression<Func<int, int>>
将不起作用:所需的信息不再可用。
至于LambdaExpression decrementorExpression = (i => i - 1);
,这是无效的,仅是因为编译器无法确定您要创建的自定义委托类型是Expression<Func<int, int>>
,anExpression<Func<int, object>>
还是Expression<MyFunc>
where MyFunc
。
最后,“表达式树可能不包含赋值运算符”,这主要是因为对于表达式树的预期用例,表达式包含赋值通常是没有意义的。但是,考虑到.NET表达式树能够表示赋值操作,这在某种程度上是任意的限制。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句