1

式ツリーの目的:

式ツリーは、使用する前にコンパイルする必要があります。これは、式ツリーが実際にはデータ構造であり、コンパイルされたコードではないためです。なんで?このコードは、ネットワークを介して、つまり他のプロセス(おそらく他のコンピューターで実行されている)で使用されることが予想されるためです。

差出人:http : //geekswithblogs.net/Martinez/archive/2009/06/29/understanding-expression-trees.aspx

「データ構造」と「コンパイル済みコード」の違いは何ですか。コンパイルされたコードはC#でどのように見えますか?!この記事では、配列またはリストを含まないすべての行がコンパイルされたコードであることを理解しています(「HumanH1 = newHuman(18);」のように)。

例を使って式ツリーとは何かを説明しないでください。この質問について明確な答えが必要です。

お時間をいただきありがとうございます

4

5 に答える 5

3

式ツリーは別の目的を果たすため、最初にコンパイルせずに式ツリーを実行することはできません。式ツリーは、実行可能コード自体ではなく、実行可能コードの柔軟な青写真として機能します(かなり柔軟性がありません)。

式ツリーは、コード自体よりも高い抽象化レベルでコード(コンパイルされているかどうかに関係なく)を記述するデータ構造です。コードとは異なり、データ構造を操作して、他のコードを記述する別の構造を作成できます。データ構造とは異なり、コードを評価して結果を生成できます。

この例を考えてみましょう。

Expression p1 = Expression.Parameter(typeof(int), "a");
Expression p2 = Expression.Parameter(typeof(int), "b");
Expression expr = Expression.Add(p1, p2);

作成中の式を示し、expr単純な式ツリーを記述しますa+b。この時点で、3つのノード(パラメーターを表す2つのノードと加算を表す1つのノード)を持つツリーのようなデータ構造ができています。式ツリーを使用して、コンテンツの調査、戻りタイプの検索など、さまざまなことができます。その構造を操作して、それに基づいて他の式を作成することもできます。たとえば、3番目のパラメーターを追加して、次のa+b+cように作成できます。

Expression p3 = Expression.Parameter(typeof(int), "c");
expr = Expression.Add(expr, p3);

ただし、実行できないことの1つは、2つの整数値を渡してそれらの合計を取得することです。式ツリーは、それらを評価するためのメソッドを提供しません。そのためには、コードの説明ではなく、実際のコードが必要です。

式ツリーは、コードの記述をコンパイルすることによってコードに変換する方法を提供します。式ツリーをラムダにしてCompile()メソッドを呼び出すと、次のようなコンパイル済みのCILコードが返されます。

ldarg.0
ldarg.1
add
ret

このコードには、評価のために2つの値を渡すことができ、合計が返されます。ただし、一部の情報は翻訳で失われます。具体的には、パラメーターの名前がaコンパイルbされたコードに存在しなくなります。これらの情報は計算を実行する必要がないため、削除されました。

于 2012-10-25T15:04:03.023 に答える
2

そのステートメントは、記述されたコンテキストで読む必要があります。式ツリーはデータ構造であるため、式ツリーがコンパイルされるまで、それが表す式を評価することはできません。

このように言いましょう。プロジェクトをビルドすると、以下の式がコンパイルされます。ただし、アプリケーションを実行すると、式ツリー(つまりデータ構造)が構築されるだけです。

Expression<Func<int, int, bool>> f = (a, b) => a < b;

式を実際に実行するには、式fをコンパイルする必要がありますf.Compile()。2つのコンパイルが発生していることに注意してください。

  • 最初のコンパイルは、コードをコンパイルするときです(つまり、上に表示されているもの)。
  • 2番目のコンパイルは、コードを実行し、ツリーによって表される実際の式がコンパイルされるときです。

アップデート

f.Compile()なしで実行できないのはなぜですか?これは私が本当に尋ねるものです

このExpression.Compileメソッドは、「式ツリーによって記述されたラムダ式を実行可能コードにコンパイルします...」実行可能コードがない場合、式ツリーを実行できません。これは、コンパイルするまでプログラムを実行できない理由を尋ねるのと同じです。

于 2012-10-25T14:52:43.207 に答える
2

C# では、C# ソース コードからの "コンパイル済みコード" は、いわゆる IL (中間言語) コードです。(これは Java バイトコードに似ています。) 公式標準では CIL (Common Intermediate Language) としても知られています。(MSIL は同じ意味で、Microsoft による CIL の実装です。)

もちろん、.NET アプリケーションが実行されると、この IL コードはさらに CLR (共通言語ランタイム、.NET の仮想マシン) によってネイティブ コード (マシン コード) に変換されます。(場合によっては、インストール時に IL コードがネイティブ コードにコンパイルされます。たとえば、mscorlib.dllWindows などの .NET アセンブリは事前にコンパイルされます。これは NGEN、つまりネイティブ イメージ生成と呼ばれます。)

この記事でデータ構造について言及している場合、それは、「通常の」C# 式または命令と同じ方法で、 (アプリケーションのコンパイル時に) 式ツリー式自体が IL コードにコンパイルされないことを意味します。代わりに、IL コードでもデータのままです(忘れないでください: 「通常の」式は IL コードでは命令になります。これは、コンパイル時に C# コンパイラによって変換されて IL コードを指示するためです)。後で、(明示的に) コンパイルするように要求できます。つまり、ツリーは実行時に評価 (コンパイル) されます。その時点まで、それらはデータ構造のままです。

同じ問題の別のアプローチ: C# ソース コードには明確に定義された構文がありますよね? C# コンパイラがそれを解析してコンパイルするとき、すべての式も解析する必要があります (「通常の」式、つまりここでは式ツリーのことは忘れてください)。たとえば、解析するときx = y + 5*z;、このデータから独自のツリーを構築する必要がありますが、これはコンパイル時に C# コンパイラの内部でのみ行われます。完了すると、たとえば、Visual Studio で「ビルドが成功しました」と表示された場合、IL コードが生成されました。つまり、アプリケーションがビルドされました。このビルド プロセス中、C# コンパイラはツリーやそのような構造も式に使用しました。

これで、非常によく似た方法で式ツリーを確認できます。式ツリーはツリー構造で式を表しますが、これらのツリーはアプリケーションで使用でき、実行時にコンパイルできます (C# コンパイラの内部ツリー構造とは異なり、実行時にコンパイルできます)。アプリケーションのビルド中に内部的に使用され、アプリケーションのビルド後に破棄されます。)

于 2012-10-25T14:56:44.670 に答える
1

式ツリー(データ構造)は、ラムダまたはコードによって表されるコードに関するメタデータと見なすことができます。式ツリーは実行可能コード(ラムダ)にコンパイルされます。式ツリーは抽象構文木(AST)です。これは、実行するコードの構造を表すオブジェクトです。(醜い詳細はこちら

したがって、質問に答えるために、式ツリーはメタデータ(データ構造を検討できると思います)であり、ラムダは実行可能な実際のビットです。

私の意見では、式ツリーの目的は、参照されている記事が維持しているものではありません。私の意見では、式ツリーを使用すると、コード内でラムダ(またはコード)を作成できるため、LINQステートメント(または他のコード)を柔軟かつ動的にすることができます。構造物を有線で送信することになるとは思いません。それを使用することもできると思いますが、式ツリーの非常に便利な目的は、やはり私の意見では、機能するコードの構成です。

これがお役に立てば幸いです。

于 2012-10-25T14:57:57.760 に答える
0

これら 2 つの概念は非常に異なっており、それらをどの基準と比較したいのかが明確ではありません。リンゴと愛の違いは何かと問うようなものです...

  • データ構造とは、データをモデル化して保存する方法の概念です。

  • コンパイルされたコードは、コンパイルの結果である遺物です。

特定のデータ構造を実装するコードを記述し、それをコンパイルできます。

于 2012-10-25T14:47:52.403 に答える