Expression trees can be said to be one of the core of LINQ, and why is it one of the core of LINQ? Because the expression tree allows C # to no longer just compile into IL, we can generate an expression tree from C #, using the result as an intermediate format, to convert it to the native language on the target platform. such as SQL. This is how LINQ to SQL is used to generate SQL.
The expression tree, introduced after. NET 3.5, is a powerful and flexible tool (such as constructing dynamic Queries in LINQ).
First look at the API interface of expression class:
namespace system.linq.expressions{////Abstract: A strongly typed lambda expression is represented as a data structure in the form of an expression tree. This class cannot be inherited. Type parameter://tdelegate:///System.Linq.Expressions.Expression ' 1 represents the type of delegate. public sealed class Expression<tdelegate>: lambdaexpression {////Abstract://Lam with expression tree description The BDA expression is compiled into executable code and the delegate that represents the lambda expression is generated. Returns the result://A delegate of type TDelegate that represents the compiled lambda expression described by System.Linq.Expressions.Expression ' 1. Public tdelegate Compile (); Summary://Generates a delegate that represents a lambda expression. Parameters://Debuginfogenerator://compiler used to mark sequence points and annotate local variables for debug information generators. Returns the result://delegate that contains the compiled version of the lambda. Public tdelegate Compile (Debuginfogenerator debuginfogenerator); Summary://Creates a new expression similar to this expression, but uses the provided child. If all children are the same, this expression is returned. Parameters://Body://System.Linq.Expressions.LambdaExpression.Body property of the result. Parameters://The System.Linq.Expressions.LambdaExpression.Parameters property of the result. Returns the result://This expression (if no children have been changed), or an expression with an updated child. Public expression<tdelegate> Update (Expression body, ienumerable<parameterexpression> parameters); Protected internal override Expression Accept (ExpressionVisitor visitor); }}
The syntax for an expression tree is as follows:
expression<func<type,returntype>> = (param) = = lamdaexpresion;
For example:
Expression<func<int, int, int>> expr = (x, y) = = X+y;
We run the above code and look at this expression tree in vs Debug mode:
You can see that the expression tree consists mainly of the following four parts:
1, Body body part
2. Parameters parameter part
3. NodeType node type
4. Lambda expression type
In the preceding code, the body is: X+y, the parameter is (x, y), NodeType is a lambda expression, and the return value is int
The body part can be an expression, but it cannot contain statements. For example: I define a delegate that a lambda expression can write
Func<int, int, int> func = (x, y) = = x + y;
You can also write this:
Func<int, int, int> func = (x, y) = = {return x + y;};
However, in an expression tree, you can only use the first notation if you compile a report error using the second notation: you cannot convert a lambda expression with a statement body to an expression tree .
In addition to the above notation, the expression tree can also be written like this:
ParameterExpression pex1 = Expression.parameter (typeof (int), "x");//First parameter parameterexpression PEX2 = Expression.parameter (typeof (int), "Y");//The second parameter binaryexpression bexp = Expression.add (pex1, PEX2);//addition var lambdaexp = Expression.lambda<func<int, int, int>> (bexp, new parameterexpression[] {pex1,pex2});
VS Debug Mode You can see that the two types of expressions generated by the expression tree are the same
Compiling an expression tree into a delegate
LambdaExpression is a type derived from expression. The generic class expression<tdelegate> is derived from LambdaExpression, where the generic parameter tdelegate must be a delegate type.
LambdaExpression has a compile method to create a delegate of the appropriate type. The expression<tdelegate> compile method returns a delegate of type TDelegate. Take a look at the following example:
Expression<func<int, int, int>> expr = (x, y) = = x + y; ParameterExpression pex1 = Expression.parameter (typeof (int), "x");//First parameter parameterexpression PEX2 = Expression.parameter (typeof (int), "Y");//second parameter binaryexpression bexp = Expression.add (pex1, PEX2);//body, addition// Using the Expression.lambda method, create a delegate type known as expressionexpression<func<int,int,int>> lambdaexp = Expression.lambda<func<int, int, int>> (bexp, new parameterexpression[] {pex1, pex2}); func<int,int,int> tdelegate = Lambdaexp.compile ();//compiled into delegated Console.WriteLine (TDelegate (1, 3)); Console.read ();
We run the above code with the result: 4. We wrote a lot of code, essentially using expression trees to calculate the results of 1+3.