Expression类的用途是什么?
我想知道包装内Expression<>
而不是代表之间的区别究竟是什么?Expression类的用途是什么?
我看到Expression<Foo>
被Linq使用了很多,但到目前为止我还没有找到任何解释这种差异和仅仅使用委托的文章。
E.g.
Func<int, bool> Is42 = (value) => value == 42;
与
Expression<Func<int, bool>> Is42 = (value) => value == 42;
通过将lambda作为委托存储,您正在存储执行某个操作的委托的特定实例。它不能被修改,你只需要调用它。一旦你有了你的委托,你在检查它的作用和内容方面的选择有限。
通过将lambda作为表达式存储,您正在存储表示代表的表达式树。它可以被操纵来做其他事情,比如改变它的参数,改变身体并使它做一些完全不同的事情。它甚至可以编译回代表,所以如果你愿意,你可以调用它。你可以很容易地检查表达式,看看它的参数是什么,它做了什么以及它是如何做的。这是查询提供程序可用于理解表达式并将其转换为其他语言(如为相应的表达式树编写SQL查询)的内容。
使用表达式动态创建代理比发出代码更容易。您可以将代码视为更高级别的表达式,这与表达式与编译器查看代码的方式非常相似,而不是低级别,并将您的代码视为IL指令。
所以对于一个表达式,你可以做的远不止一个简单的匿名委托。虽然它不是真正免费的,但如果您运行编译的表达式与常规方法或匿名代理相比,性能会受到影响。但是这可能不是一个问题,因为使用表达式的其他好处对您而言可能很重要。
Func<>
只是一个委托类型。一个表达式,一个operations完整树的运行时表示,它可以选择性地在运行时编译成一个委托。它是由像Linq-to-SQL这样的表达式解析器进行解析来生成SQL语句或执行其他聪明事情的树。当您将lambda分配给Expression类型时,编译器会生成此表达式树以及通常的IL代码。 More on expression trees。
提供从中派生出代表 表达式树节点的类的基类。
System.Linq.Expressions.BinaryExpression
System.Linq.Expressions.BlockExpression
System.Linq.Expressions.ConditionalExpression
System.Linq.Expressions.ConstantExpression
System.Linq.Expressions.DebugInfoExpression
System.Linq.Expressions.DefaultExpression
System.Linq.Expressions.DynamicExpression
System.Linq.Expressions.GotoExpression
System.Linq.Expressions.IndexExpression
System.Linq.Expressions.InvocationExpression
System.Linq.Expressions.LabelExpression
System.Linq.Expressions.LambdaExpression
System.Linq.Expressions.ListInitExpression
System.Linq.Expressions.LoopExpression
System.Linq.Expressions.MemberExpression
System.Linq.Expressions.MemberInitExpression
System.Linq.Expressions.MethodCallExpression
System.Linq.Expressions.NewArrayExpression
System.Linq.Expressions.NewExpression
System.Linq.Expressions.ParameterExpression
System.Linq.Expressions.RuntimeVariablesExpression
System.Linq.Expressions.SwitchExpression
System.Linq.Expressions.TryExpression
System.Linq.Expressions.TypeBinaryExpression
System.Linq.Expressions.UnaryExpression
http://msdn.microsoft.com/en-us/library/system.linq.expressions.expression.aspx
表达树表示可以被分析,并且例如变成SQL查询LINQ表达式。
为了说明其他的答案,如果你编译那些2倍的表达,并在编译器生成的代码有看,这我你会看到什么:
Func<int, bool> Is42 = (value) => value == 42;
Func<int, bool> Is42 = new Func<int, bool>((@value) => value == 42);
Expression<Func<int, bool>> Is42 = (value) => value == 42;
ParameterExpression[] parameterExpressionArray;
ParameterExpression parameterExpression = Expression.Parameter(typeof(int), "value");
Expression<Func<int, bool>> Is42 = Expression.Lambda<Func<int, bool>>(Expression.Equal(parameterExpression, Expression.Constant(42, typeof(int))), new ParameterExpression[] { parameterExpression });
无论其他人写什么(这是完全正确的),我会通过Expression
类添加,您可以在运行时创建新方法。有一些限制。并非所有在C#中可以做的事情都可以在Expression
树中完成(至少在.NET 3.5中,使用.NET 4.0,他们已经添加了大量可能的Expression
“类型”)。使用它可以(例如)创建一个动态查询并将其传递给LINQ-to-SQL,或者根据用户的输入做一些过滤......(如果你想要的话你可以使用CodeDom来做到这一点是一种与LINQ-to-SQL不兼容的动态方法,但是直接发送IL代码是相当困难的:-))
这对我来说很完美,非常感谢:-) – Steffen