C# 式ツリー(Expression Tree)入門

式ツリー(Expression Tree)は、ラムダ式をコードとしてではなく「データ構造」として扱う仕組みです。Entity Framework などの ORM が、ラムダ式を SQL に変換できるのはこの機能のおかげです。

式ツリーとは

通常、ラムダ式はコンパイル時に実行可能なコード(デリゲート)に変換されます。一方、式ツリーとして扱うと、ラムダ式の構造そのものがオブジェクトとして保持されます。

using System.Linq.Expressions;

// デリゲート:実行可能なコード
Func<int, int> funcSquare = x => x * x;

// 式ツリー:式の構造を表すデータ
Expression<Func<int, int>> exprSquare = x => x * x;

見た目は同じラムダ式ですが、型が FuncExpression<Func> かで扱いが変わります。

式ツリーの構造を見る

式ツリーは、式の各部分をノードとして持つ木構造になっています。

Expression&lt;Func&lt;int, int&gt;&gt; expr = x =&gt; x * x;

Console.WriteLine(expr.Body);       // (x * x)
Console.WriteLine(expr.Parameters[0]); // x
Console.WriteLine(expr.NodeType);   // Lambda

Body プロパティで式の本体にアクセスでき、さらにその内部構造を辿ることもできます。

式ツリーをコンパイルして実行

式ツリーは Compile() メソッドでデリゲートに変換し、実行できます。

Expression&lt;Func&lt;int, int, int&gt;&gt; expr = (a, b) =&gt; a + b;

// 式ツリーをデリゲートにコンパイル
Func&lt;int, int, int&gt; func = expr.Compile();

Console.WriteLine(func(3, 5)); // 8

Entity Framework での活用

Entity Framework では、式ツリーを解析して SQL クエリに変換します。

// このラムダ式は式ツリーとして解釈される
var query = dbContext.Users
    .Where(u =&gt; u.Age &gt;= 20 &amp;&amp; u.IsActive);

Where に渡されたラムダ式は、実行されるのではなく解析されます。そして u.Age >= 20 && u.IsActive という条件が SQL の WHERE 句に変換されるのです。

LINQ to Objects(Func を使用)

メモリ上のコレクションに対して、ラムダ式がそのまま実行される

LINQ to Entities(Expression を使用)

ラムダ式が解析され、SQL などの別言語に変換される

制限事項

式ツリーに変換できるのは「式形式ラムダ」のみです。文形式ラムダは式ツリーにできません。

// OK:式形式
Expression&lt;Func&lt;int, int&gt;&gt; valid = x =&gt; x * 2;

// エラー:文形式は式ツリーにできない
// Expression&lt;Func&lt;int, int&gt;&gt; invalid = x =&gt; { return x * 2; };

式ツリーは高度な機能ですが、ORM やコード生成など、C# のエコシステムを支える重要な基盤となっています。