Expression 类的目的是啥?
Posted
技术标签:
【中文标题】Expression 类的目的是啥?【英文标题】:What's the purpose of the Expression class?Expression 类的目的是什么? 【发布时间】:2011-12-07 15:11:01 【问题描述】:我想知道在 Expression<>
中包装委托和不包装之间到底有什么区别?
我看到Expression<Foo>
经常与 LinQ 一起使用,但到目前为止,我还没有找到任何文章解释这与仅使用委托之间的区别。
例如
Func<int, bool> Is42 = (value) => value == 42;
对比
Expression<Func<int, bool>> Is42 = (value) => value == 42;
【问题讨论】:
【参考方案1】:通过将 lambda 存储为委托,您将存储执行某些操作的委托的特定实例。它不能被修改,你只是调用它。一旦你有了你的委托,你在检查它做什么和做什么方面的选择是有限的。
通过将 lambda 存储为表达式,您将存储表示委托的表达式树。它可以被操纵来做其他事情,比如改变它的参数,改变身体,让它做一些完全不同的事情。它甚至可以被编译回一个委托,所以如果你愿意,你可以调用它。您可以轻松地检查表达式以查看其参数是什么、它做了什么以及它是如何做的。这是查询提供者可以用来理解表达式并将其翻译成另一种语言的东西(例如为相应的表达式树编写 SQL 查询)。
使用表达式动态创建委托也比发出代码要容易得多。您可以将更高级别的代码视为表达式,这与编译器查看代码的方式非常相似,而不是进入低级别并将您的代码视为 IL 指令。
因此,使用表达式,您可以做的不仅仅是一个简单的匿名委托。虽然它不是真正免费的,但如果您运行编译表达式,与常规方法或匿名委托相比,性能会受到影响。但这可能不是问题,因为使用表达式的其他好处可能对您很重要。
【讨论】:
【参考方案2】:Func<>
只是一个委托类型。表达式是operations 的完整树的运行时表示,可以选择在运行时将其编译为委托。正是这棵树由表达式解析器(如 Linq-to-SQL)解析,以生成 SQL 语句或做其他聪明的事情。当您将 lambda 分配给 Expression 类型时,编译器会生成此表达式树以及通常的 IL 代码。 More on expression trees.
【讨论】:
【参考方案3】:为了说明其他答案,如果您编译这两个表达式并查看编译器生成的代码,您将看到以下内容:
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 );
【讨论】:
他在问有什么区别,生成的代码是不言自明的区别。【参考方案4】:Expression Trees 允许您在代码中检查表达式中的代码。
例如,如果您传递此表达式:o => o.Name
,您的代码可能会发现在表达式内部正在访问 Name
属性。
【讨论】:
【参考方案5】:提供代表代表的类的基类 派生表达式树节点。
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 查询。
【讨论】:
【参考方案6】:对于其他人写的任何内容(完全正确),我将通过Expression
类添加,您可以在运行时创建新方法。有一些限制。并非您在 C# 中可以做的所有事情都可以在 Expression
树中完成(至少在 .NET 3.5 中。在 .NET 4.0 中,他们添加了大量可能的 Expression
“类型”)。它的用途可以是(例如)创建一个动态查询并将其传递给 LINQ-to-SQL 或根据用户的输入进行一些过滤......(如果你想要的话,你总是可以用 CodeDom 做到这一点是一种与 LINQ-to-SQL 不兼容的动态方法,但直接发出 IL 代码相当困难 :-))
【讨论】:
以上是关于Expression 类的目的是啥?的主要内容,如果未能解决你的问题,请参考以下文章
Haskell let-expression 中出现奇怪的类型错误——问题是啥?
Expression<Func<T,bool>> 声明是啥意思?
[Error] expected expression before','token 是啥意思?