式ツリー (C#)Expression Trees (C#)

式ツリーでは、コードがツリー状のデータ構造で表示されます。各ノードは 1 つの式に対応しています。たとえば、メソッドの呼び出しや x < y のような二項演算などです。Expression trees represent code in a tree-like data structure, where each node is an expression, for example, a method call or a binary operation such as x < y.

式ツリーで表されるコードはコンパイルおよび実行できます。You can compile and run code represented by expression trees. これによって、実行可能なコードの動的な変更、さまざまなデータベースでの LINQ クエリの実行、および動的クエリの作成が可能になります。This enables dynamic modification of executable code, the execution of LINQ queries in various databases, and the creation of dynamic queries. LINQ の式ツリーの詳細については、「How to: Use Expression Trees to Build Dynamic Queries (C#)」 (方法: 式ツリーを使用して動的クエリをビルドする (C#)) を参照してください。For more information about expression trees in LINQ, see How to: Use Expression Trees to Build Dynamic Queries (C#).

また、式ツリーを動的言語ランタイム (DLR) に使用することで、動的言語と .NET Framework 間の相互運用性が実現し、コンパイラ ライターで Microsoft Intermediate language (MSIL) ではなく式ツリーを出力できるようになります。Expression trees are also used in the dynamic language runtime (DLR) to provide interoperability between dynamic languages and the .NET Framework and to enable compiler writers to emit expression trees instead of Microsoft intermediate language (MSIL). DLR の詳細については、「動的言語ランタイムの概要」を参照してください。For more information about the DLR, see Dynamic Language Runtime Overview.

匿名のラムダ式に基づいて、C# と Visual Basic コンパイラで式ツリーを作成できます。または、System.Linq.Expressions 名前空間を使用して手動で式ツリーを作成できます。You can have the C# or Visual Basic compiler create an expression tree for you based on an anonymous lambda expression, or you can create expression trees manually by using the System.Linq.Expressions namespace.

ラムダ式からの式ツリーの作成Creating Expression Trees from Lambda Expressions

ラムダ式が Expression<TDelegate> 型の変数に割り当てられている場合、コンパイラはラムダ式を表す式ツリーを構築するコードを出力します。When a lambda expression is assigned to a variable of type Expression<TDelegate>, the compiler emits code to build an expression tree that represents the lambda expression.

C# コンパイラは、式形式のラムダ (つまり単一行のラムダ) からのみ式ツリーを生成できます。The C# compiler can generate expression trees only from expression lambdas (or single-line lambdas). ステートメント形式のラムダ (つまり複数行のラムダ) は解析できません。It cannot parse statement lambdas (or multi-line lambdas). C# のラムダ式の詳細については、「ラムダ式」を参照してください。For more information about lambda expressions in C#, see Lambda Expressions.

次のコード例は、ラムダ式 num => num < 5 を表す式ツリーを C# コンパイラで作成する方法を示しています。The following code examples demonstrate how to have the C# compiler create an expression tree that represents the lambda expression num => num < 5.

Expression<Func<int, bool>> lambda = num => num < 5;  

API を使用した式ツリーの作成Creating Expression Trees by Using the API

API を使用して式ツリーを作成するには、Expression クラスを使用します。To create expression trees by using the API, use the Expression class. このクラスには、特定の型を持つ式ツリー ノードを作成する静的ファクトリ メソッドが含まれます。たとえば、変数またはパラメーターを表す ParameterExpression や、メソッドの呼び出しを表す MethodCallExpression などです。This class contains static factory methods that create expression tree nodes of specific types, for example, ParameterExpression, which represents a variable or parameter, or MethodCallExpression, which represents a method call. ParameterExpressionMethodCallExpression などの式固有の型も、System.Linq.Expressions 名前空間で定義されます。ParameterExpression, MethodCallExpression, and the other expression-specific types are also defined in the System.Linq.Expressions namespace. これらの型は、Expression 抽象型から派生したものです。These types derive from the abstract type Expression.

次のコード例は、API を使用して、ラムダ式 num => num < 5 を表す式ツリーを作成する方法を示しています。The following code example demonstrates how to create an expression tree that represents the lambda expression num => num < 5 by using the API.

// Add the following using directive to your code file:  
// using System.Linq.Expressions;  

// Manually build the expression tree for   
// the lambda expression num => num < 5.  
ParameterExpression numParam = Expression.Parameter(typeof(int), "num");  
ConstantExpression five = Expression.Constant(5, typeof(int));  
BinaryExpression numLessThanFive = Expression.LessThan(numParam, five);  
Expression<Func<int, bool>> lambda1 =  
    Expression.Lambda<Func<int, bool>>(  
        numLessThanFive,  
        new ParameterExpression[] { numParam });  

.NET Framework 4 以降の式ツリー API は、割り当て式、制御フロー式 (ループ、条件ブロック)、および try-catch ブロックもサポートしています。In .NET Framework 4 or later, the expression trees API also supports assignments and control flow expressions such as loops, conditional blocks, and try-catch blocks. API を使用すると、C# コンパイラのラムダ式から作成できる式ツリーよりも複雑な式ツリーを作成できます。By using the API, you can create expression trees that are more complex than those that can be created from lambda expressions by the C# compiler. 次の例は、数値の階乗を計算する式ツリーを作成する方法を示しています。The following example demonstrates how to create an expression tree that calculates the factorial of a number.

// Creating a parameter expression.  
ParameterExpression value = Expression.Parameter(typeof(int), "value");  

// Creating an expression to hold a local variable.   
ParameterExpression result = Expression.Parameter(typeof(int), "result");  

// Creating a label to jump to from a loop.  
LabelTarget label = Expression.Label(typeof(int));  

// Creating a method body.  
BlockExpression block = Expression.Block(  
    // Adding a local variable.  
    new[] { result },  
    // Assigning a constant to a local variable: result = 1  
    Expression.Assign(result, Expression.Constant(1)),  
    // Adding a loop.  
        Expression.Loop(  
    // Adding a conditional block into the loop.  
           Expression.IfThenElse(  
    // Condition: value > 1  
               Expression.GreaterThan(value, Expression.Constant(1)),  
    // If true: result *= value --  
               Expression.MultiplyAssign(result,  
                   Expression.PostDecrementAssign(value)),  
    // If false, exit the loop and go to the label.  
               Expression.Break(label, result)  
           ),  
    // Label to jump to.  
       label  
    )  
);  

// Compile and execute an expression tree.  
int factorial = Expression.Lambda<Func<int, int>>(block, value).Compile()(5);  

Console.WriteLine(factorial);  
// Prints 120.  

詳細については、「Generating Dynamic Methods with Expression Trees in Visual Studio 2010 (Visual Studio 2010 での式ツリーによる動的メソッドの生成)」を参照し、Visual Studio 2010 以降のバージョンについても同じ方法を適用してください。For more information, see Generating Dynamic Methods with Expression Trees in Visual Studio 2010, which also applies to later versions of Visual Studio.

式ツリーの解析Parsing Expression Trees

次のコード例は、ラムダ式 num => num < 5 を表す式ツリーを各部分に分解する方法を示しています。The following code example demonstrates how the expression tree that represents the lambda expression num => num < 5 can be decomposed into its parts.

// Add the following using directive to your code file:  
// using System.Linq.Expressions;  

// Create an expression tree.  
Expression<Func<int, bool>> exprTree = num => num < 5;  

// Decompose the expression tree.  
ParameterExpression param = (ParameterExpression)exprTree.Parameters[0];  
BinaryExpression operation = (BinaryExpression)exprTree.Body;  
ParameterExpression left = (ParameterExpression)operation.Left;  
ConstantExpression right = (ConstantExpression)operation.Right;  

Console.WriteLine("Decomposed expression: {0} => {1} {2} {3}",  
                  param.Name, left.Name, operation.NodeType, right.Value);  

// This code produces the following output:  

// Decomposed expression: num => num LessThan 5  

式ツリーの不変性Immutability of Expression Trees

式ツリーは変更できません。Expression trees should be immutable. つまり、式ツリーを変更するには、既存の式ツリーをコピーしてツリー内のノードを置き換えることで、新しい式ツリーを作成する必要があります。This means that if you want to modify an expression tree, you must construct a new expression tree by copying the existing one and replacing nodes in it. 式ツリー ビジターを使用して、既存の式ツリーを走査することができます。You can use an expression tree visitor to traverse the existing expression tree. 詳細については、「方法: 式ツリーを変更する (C#)」を参照してください。For more information, see How to: Modify Expression Trees (C#).

式ツリーのコンパイルCompiling Expression Trees

Expression<TDelegate> 型に含まれる Compile メソッドにより、式ツリーが表すコードを実行可能なデリゲートにコンパイルします。The Expression<TDelegate> type provides the Compile method that compiles the code represented by an expression tree into an executable delegate.

次のコード例は、式ツリーをコンパイルして結果のコードを実行する方法を示しています。The following code example demonstrates how to compile an expression tree and run the resulting code.

// Creating an expression tree.  
Expression<Func<int, bool>> expr = num => num < 5;  

// Compiling the expression tree into a delegate.  
Func<int, bool> result = expr.Compile();  

// Invoking the delegate and writing the result to the console.  
Console.WriteLine(result(4));  

// Prints True.  

// You can also use simplified syntax  
// to compile and run an expression tree.  
// The following line can replace two previous statements.  
Console.WriteLine(expr.Compile()(4));  

// Also prints True.  

詳細については、「方法: 式ツリーを実行する (C#)」を参照してください。For more information, see How to: Execute Expression Trees (C#).

参照See Also