Wat*_* v2 2 .net c# linq lambda linq-expressions
实际上,有四个相关的问题:
1)为什么可以这样做?
Expression<Func<int, int>> incrementorExpression = (i => i + 1);
Run Code Online (Sandbox Code Playgroud)
但是不能这样做?
LambdaExpression decrementorExpression = (i => i - 1);
Run Code Online (Sandbox Code Playgroud)
在第二种情况下,编译器因此报告:"无法将lambda表达式转换为类型'System.Linq.Expressions.LambdaExpression',因为它不是委托类型"
2)如果是的铸造TDelegate和Expression<TDelegate>申报?我想我记得过去见过它但现在似乎无法找到它.但我无法确定我是否看到了它.
3)当我这样做时:
Expression<Func<int, int>> incrementExpression = (i => ++i);
Run Code Online (Sandbox Code Playgroud)
编译器说:"表达式树可能不包含赋值运算符." 为什么会这样?
4)如果我能做到这一点:
Expression<Func<int, int>> incrementorExpression = (i => i + 1);
Run Code Online (Sandbox Code Playgroud)
那么,为什么我不能做这个?
public Expression<Func<T>> ToExpression<T>(Func<T> func)
{
return func;
}
Run Code Online (Sandbox Code Playgroud)
小智 7
你几乎找到了答案.
i => i + 1不是Func<int, int>.这是一个lambda表达式.Lambda表达式可以转换为匹配的委托类型或匹配的表达式树类型.
如果将lambda表达式转换为委托类型,则编译器会将其编译为具有指定效果的IL代码.
如果将lambda表达式转换为表达式树类型,则编译器会将其编译为IL,以生成表示您在lambda表达式中编写的内容的表达式树.表达式树适用于以后通过库进行解析,因此表达式树与您编写的代码紧密匹配非常重要.
Func<int, int> f = i => i + 1; // okay, creates delegate.
Expression<Func<int, int>> e = i => i + 1; // okay, creates expression tree.
Run Code Online (Sandbox Code Playgroud)
无法从其f执行的操作中检索任何信息.从它的委托类型可知,它需要一个int并返回一个int,但除此之外,它是一个黑盒子.你输了一个数字,然后你得到一个数字,但你不再知道如何.
e另一方面,存储1添加到名为的参数的事实,i甚至1出现在RHS的RHS上+.
存储的这些额外信息e通常对于解释表达式树的库是必不可少的,因此隐式转换Func<int, int>为Expression<Func<int, int>>just将不起作用:所需信息不再可用.
至于LambdaExpression decrementorExpression = (i => i - 1);,这是无效的,因为编译器无法确定您是否希望a Expression<Func<int, int>>,an Expression<Func<int, object>>或Expression<MyFunc>where MyFunc是您创建的自定义委托类型.
最后"表达式树可能不包含赋值运算符",这主要是因为对于表达式树的预期用例,表达式通常对包含赋值没有意义.但是,考虑到.NET表达式树能够表示赋值操作,这有点任意限制.