C# の式ツリーの簡単な紹介

黄舟
リリース: 2017-09-16 11:08:45
オリジナル
2096 人が閲覧しました

Linq の核の 1 つとも言える式ツリー。なぜそれが Linq の核の 1 つなのか?式ツリーにより、C# は単に IL にコンパイルされなくなるため、C# を通じて式ツリーを生成し、その結果を中間形式として使用し、それをターゲット プラットフォーム上のネイティブ言語に変換できます。 SQLなど。これは、一般的に使用される Linq to sql が SQL を生成する方法です。

式ツリーは、.NET 3.5 の後に導入されました。これは、LINQ で動的クエリを構築するために使用される強力で柔軟なツールです。

まず、Expression クラスの API インターフェイスを見てみましょう:

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);
    }
}
ログイン後にコピー

式ツリーの構文は次のとおりです:


Expression<Func<type,returnType>> = (param) => lamdaexpresion;
ログイン後にコピー

例:


Expression<Func<int, int, int>> expr = (x, y) => x+y;
ログイン後にコピー

上記のコードを実行しますこれを VS デバッグ シミュレーションの式ツリーの下に表示します:

式ツリーは主に次の 4 つの部分で構成されていることがわかります:

1. 本体の主要部分

2. パラメータ パラメータ 部分

3. NodeType ノードタイプ

4. ラムダ式のタイプ

上記のコードでは、本体は x+y、パラメータは (x, y)、NodeType は Lambda 式です。戻り値は int です

主要部分は式にすることができますが、ステートメントを含めることはできません。例: デリゲートを定義し、ラムダ式は次のように書くことができます


Func<int, int, int> func = (x, y) => x + y;
ログイン後にコピー

または次のように書くことができます:


Func<int, int, int> func = (x, y) => { return x + y; };
ログイン後にコピー

ただし、式ツリーでは最初のもののみを使用できます。 2 番目の方法を使用する場合、コンパイル レポートの作成エラー: ステートメント本体を含むラムダ式を式ツリーに変換できません

上記の記述方法に加えて、式ツリーは次のように記述することもできます:

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 });
ログイン後にコピー


VS デバッグ モードでは、2 つの記述方法によって生成された式ツリーが同じ

式を置き換えます。ツリーはデリゲートにコンパイルされます

LambdaExpression は、Expression から派生した型です。ジェネリック クラス Expression は LambdaExpression から派生し、ジェネリック パラメータ TDelegate はデリゲート型である必要があります。

LambdaExpression には、適切な型のデリゲートを作成する Compile メソッドがあります。 Expression の Compile メソッドは、TDelegate 型のデリゲートを返します。次の例を見てみましょう:

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();
ログイン後にコピー

上記のコードを実行すると、結果は次のようになります: 4.私たちは、基本的に式ツリーを使用して 1+3 の結果を計算する多くのコードを書きました。

以上がC# の式ツリーの簡単な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート