Expression类的目的是什么?

时间:2011-10-14 09:52:16

标签: c# lambda expression-trees

我想知道在Expression<>内包装委托的确切区别是什么?

我看到Expression<Foo>在LinQ中被大量使用,但到目前为止,我还没有发现任何解释它之间差异的文章,只是使用了委托。

E.g。

Func<int, bool> Is42 = (value) => value == 42;

VS

Expression<Func<int, bool>> Is42 = (value) => value == 42;

6 个答案:

答案 0 :(得分:60)

通过将lambda存储为委托,您将存储执行某些操作的委托的特定实例。它无法修改,你只需要调用它。一旦你有了代表,你就可以选择有限的方法来检查它的功能和作用。

通过将lambda存储为表达式,您将存储表示委托的表达式树。它可以被操纵来做其他事情,比如改变它的参数,改变身体并让它做一些截然不同的事情。它甚至可以编译回代表,所以如果你愿意,你可以打电话给代表。您可以轻松地检查表达式,以查看其参数是什么,它做了什么以及如何做。这是查询提供程序可以用来理解表达式并将其转换为另一种语言(例如为相应的表达式树编写SQL查询)。

使用表达式动态创建委托比发出代码要容易得多。您可以将更高级别的代码视为与编译器查看代码而非低级别并将代码视为IL指令非常相似的表达式。

因此,使用表达式,您可以做的不仅仅是一个简单的匿名委托。虽然它不是真正免费的,但如果你运行编译表达式与常规方法或匿名委托相比,性能将受到影响。但这可能不是问题,因为使用表达式的其他好处对您来说可能很重要。

答案 1 :(得分:14)

Func<>只是一种委托类型。表达式是operations的完整树的运行时表示,可选地,可以在运行时将其编译为委托。这个树由Linq-to-SQL之类的Expression解析器解析,以生成SQL语句或执行其他聪明的操作。将lambda指定给Expression类型时,编译器会生成此表达式树以及常用的IL代码。 More on expression trees

答案 2 :(得分:12)

为了说明其他答案,如果您编译这两个表达式并查看编译器生成的代码,那么您将看到:

<强> 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 });

答案 3 :(得分:4)

  

提供表示类的基类   表达式树节点是派生的。

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

表达式树表示可以分析的linq表达式,例如转换为SQL查询。

答案 4 :(得分:4)

Expression Trees允许您在代码中检查表达式中的代码。

例如,如果您传递了此表达式:o => o.Name,您的代码可能会发现表达式中正在访问Name属性。

答案 5 :(得分:2)

对于其他人所写的内容(完全正确),我将通过Expression类添加它,您可以在运行时创建新方法。有一些限制。并非您在C#中可以执行的所有操作都可以在Expression树中完成(至少在.NET 3.5中。使用.NET 4.0,它们添加了大量可能的Expression“类型”)。使用它可以(例如)创建动态查询并将其传递给LINQ-to-SQL或根据用户的输入进行一些过滤...(如果你想要的话,你总是可以用CodeDom做到这一点是一个与LINQ-to-SQL不兼容的动态方法,但直接发送IL代码非常困难:-))