开发者

What's the purpose of the Expression class?

开发者 https://www.devze.com 2023-04-12 19:32 出处:网络
I\'m wondering what exactly is the difference between wrapping a delegate inside Expression<> and not ?

I'm wondering what exactly is the difference between wrapping a delegate inside Expression<> and not ?

I'm seeing Expression<Foo> being used a lot with LinQ, but so far I've not found any article that explains the difference between this, and just using a delegate.

E.g.

Func<int, bool> Is4开发者_如何学JAVA2 = (value) => value == 42;

vs.

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


tl;dr, To have an expression is like having the source code of an application, and a delegate is an executable to run the application. An expression can be thought of as the "source" (i.e., syntax tree) of the code that would run. A delegate is a specific compilation that you would run and does the thing.


By storing a lambda as a delegate, you are storing a specific instance of a delegate that does some action. It can't be modified, you just call it. Once you have your delegate, you have limited options in inspecting what it does and whatnot.

By storing a lambda as an expression, you are storing an expression tree that represents the delegate. It can be manipulated to do other things like changing its parameters, changing the body and make it do something radically different. It could even be compiled back to a delegate so you may call it if you wish. You can easily inspect the expression to see what its parameters are, what it does and how it does it. This is something that a query provider can use to understand and translate an expression to another language (such as write an SQL query for a corresponding expression tree).

It is also a whole lot easier to create a delegate dynamically using expressions than it is emitting the code. You can think of your code at a higher level as expressions that is very similar to how a compiler views code instead of going low-level and view your code as IL instructions.

So with an expression, you are capable to do much more than a simple anonymous delegate. Though it's not really free, performance will take a hit if you run compiled expressions compared to a regular method or an anonymous delegate. But that might not be an issue as the other benefits to using expressions may be important to you.


Func<> is just a delegate type. An Expression is a runtime representation of the complete tree of operations which, optionally, may be compiled at runtime into a delegate. It's this tree that is parsed by Expression parsers like Linq-to-SQL to generate SQL statements or do other clever things. When you assign a lambda to an Expression type, the compiler generates this expression tree as well as the usual IL code. More on expression trees.


To illustrate other answers, if you compile those 2 expressions and have look at the compiler generated code, this i what you will see:

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 Trees allow you to inspect the code inside the expression, in your code.

For example, if you passed this expression: o => o.Name, your code could find out that the Name property was being accessed inside the expression.


Provides the base class from which the classes that represent expression tree nodes are derived.

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

Expression tree represents linq expression that can be analyzed and for example turned into SQL query.


To whatever the other wrote (that is completely correct) I'll add that through the Expression class you can create new methods at runtime. There are some limits. Not all the things you can do in C# can be done in an Expression tree (at least in .NET 3.5 . With .NET 4.0 they have added a great number of possible Expression "types"). The use of this could be (for example) to create a dynamic query and pass it to LINQ-to-SQL or do some filtering based on the input of the user... (you could always do this with CodeDom if all you wanted was a dynamic method incompatible with LINQ-to-SQL, but emitting directly IL code is quite difficult :-) )

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号