式ツリーは別の目的を果たすため、最初にコンパイルせずに式ツリーを実行することはできません。式ツリーは、実行可能コード自体ではなく、実行可能コードの柔軟な青写真として機能します(かなり柔軟性がありません)。
式ツリーは、コード自体よりも高い抽象化レベルでコード(コンパイルされているかどうかに関係なく)を記述するデータ構造です。コードとは異なり、データ構造を操作して、他のコードを記述する別の構造を作成できます。データ構造とは異なり、コードを評価して結果を生成できます。
この例を考えてみましょう。
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
されたコードに存在しなくなります。これらの情報は計算を実行する必要がないため、削除されました。