A brief introduction to expression trees in C#

黄舟
Release: 2017-09-16 11:08:45
Original
2074 people have browsed it

Expression tree can be said to be one of the cores of Linq. Why is it one of the cores of Linq? Because the expression tree makes c# no longer just compile to IL, we can generate an expression tree through c#, use the result as an intermediate format, and convert it into the native language on the target platform. Such as SQL. This is how our commonly used Linq to sql generates SQL.

Expression tree was introduced after .NET 3.5. It is a powerful and flexible tool (such as used to construct dynamic queries in LINQ).

Let’s first take a look at the API interface of the Expression class:

namespace System.Linq.Expressions
{
    //
    // 摘要:
    //     以表达式目录树的形式将强类型 lambda 表达式表示为数据结构。此类不能被继承。
    //
    // 类型参数:
    //   TDelegate:
    //     System.Linq.Expressions.Expression`1 表示的委托的类型。
    public sealed class Expression<TDelegate> : LambdaExpression
    {
        //
        // 摘要:
        //     将表达式树描述的 lambda 表达式编译为可执行代码,并生成表示该 lambda 表达式的委托。
        //
        // 返回结果:
        //     一个 TDelegate 类型的委托,它表示由 System.Linq.Expressions.Expression`1 描述的已编译的 lambda 表达式。
        public TDelegate Compile();
        //
        // 摘要:
        //     生成表示 lambda 表达式的委托。
        //
        // 参数:
        //   debugInfoGenerator:
        //     编译器用于标记序列点并批注局部变量的调试信息生成器。
        //
        // 返回结果:
        //     包含 lambda 的已编译版本的委托。
        public TDelegate Compile(DebugInfoGenerator debugInfoGenerator);
        //
        // 摘要:
        //     创建一个与此表达式类似的新表达式,但使用所提供的子级。如果所有子级都相同,则将返回此表达式。
        //
        // 参数:
        //   body:
        //     结果的 System.Linq.Expressions.LambdaExpression.Body 属性。
        //
        //   parameters:
        //     结果的 System.Linq.Expressions.LambdaExpression.Parameters 属性。
        //
        // 返回结果:
        //     此表达式(如果未更改任何子级),或带有更新的子级的表达式。
        public Expression<TDelegate> Update(Expression body, IEnumerable<ParameterExpression> parameters);
        protected internal override Expression Accept(ExpressionVisitor visitor);
    }
}
Copy after login

The syntax of the expression tree is as follows:


Expression<Func<type,returnType>> = (param) => lamdaexpresion;
Copy after login

For example:


Expression<Func<int, int, int>> expr = (x, y) => x+y;
Copy after login

We run the above code and view this expression tree under VS debugging mode:

You can see The expression tree is mainly composed of the following four parts:

1. Body part

2. Parameters part part

3. NodeType node type

4.Lambda expression type

In the above code, the main body is: x+y, and the parameters are (x, y), NodeType is Lambda expression, and the return value is int

The main part can be an expression, but it cannot contain statements. For example: I define a delegate. The Lambda expression can be written like this


Func<int, int, int> func = (x, y) => x + y;
Copy after login

or it can be written like this:


Func<int, int, int> func = (x, y) => { return x + y; };
Copy after login

However, in the expression tree type, only the first way of writing can be used. If the second way of writing is used, the compiler will report an error: Cannot convert a lambda expression with a statement body into an expression tree.

In addition to the above writing method, the expression tree can also be written like this:

ParameterExpression pex1 = Expression.Parameter(typeof(int), "x");//第一个参数
ParameterExpression pex2 = Expression.Parameter(typeof(int), "y");//第二个参数

BinaryExpression bexp = Expression.Add(pex1, pex2);//加法

var lambdaExp = Expression.Lambda<Func<int, int, int>>(bexp, new ParameterExpression[] {pex1,pex2 });
Copy after login


VS debugging In mode, you can see that the expression trees generated by the two writing methods are the same

Compile the expression tree into a delegate

LambdaExpression is a type derived from Expression. The generic class Expression is derived from LambdaExpression, where the generic parameter TDelegate must be a delegate type.

LambdaExpression has a Compile method that creates a delegate of the appropriate type. The Compile method of Expression returns a delegate of type TDelegate. Let’s take a look at the following example:

Expression<Func<int, int, int>> expr = (x, y) => x + y;

ParameterExpression pex1 = Expression.Parameter(typeof(int), "x");//第一个参数
ParameterExpression pex2 = Expression.Parameter(typeof(int), "y");//第二个参数

BinaryExpression bexp = Expression.Add(pex1, pex2);//主体,加法

//使用Expression.Lambda方法,创建一个委托类型已知的Expression
Expression<Func<int,int,int>> lambdaExp 
    = Expression.Lambda<Func<int, int, int>>(bexp, new ParameterExpression[] { pex1, pex2 });

Func<int,int,int> tDelegate = lambdaExp.Compile();//编译成委托

Console.WriteLine(tDelegate(1, 3));

Console.Read();
Copy after login

We run the above code and the result is: 4. We wrote a lot of code, which essentially calculated the result of 1+3 using an expression tree.

The above is the detailed content of A brief introduction to expression trees in C#. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template