0Pricing
C# Academy · レッスン

式のコンパイルと実行

式ツリーを実行可能なデリゲートに変換します。

「式のコンパイルと実行」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。

ツリーからデリゲートへ

式ツリーは、コンパイルするまでデータにすぎません。Expression<TDelegate>.Compile() は、ツリーを呼び出し可能な実際のデリゲートに変換します。

using System;
using System.Linq.Expressions;

Expression<Func<int, int>> tree = x => x + 1;
Func<int, int> fn = tree.Compile();
Console.WriteLine(fn(5)); // 6

手動で構築したツリーをコンパイルする

手動で構築したツリーも同じ方法でコンパイルでき、動作するデリゲートが生成されます。

using System;
using System.Linq.Expressions;

var x = Expression.Parameter(typeof(int), "x");
var body = Expression.Multiply(x, Expression.Constant(3));
var lambda = Expression.Lambda<Func<int, int>>(body, x);
var fn = lambda.Compile();
Console.WriteLine(fn(4)); // 12

結果を呼び出す

コンパイル済みのデリゲートは他のデリゲートと同じように動作します。呼び出したり、保存したり、受け渡したりできます。

using System;
using System.Linq.Expressions;

Expression<Func<int, int, int>> addExpr = (a, b) => a + b;
var add = addExpr.Compile();
Console.WriteLine(add(2, 3)); // 5
Console.WriteLine(add(10, 20)); // 30

コンパイルは無料ではない

コンパイルには実行時コストがかかるため、呼び出すたびにコンパイルするのではなく、生成されたデリゲートをキャッシュして再利用してください。

using System;
using System.Linq.Expressions;

Expression<Func<int, int>> tree = x => x * x;
var square = tree.Compile(); // compile once
for (int i = 1; i <= 3; i++)
    Console.Write(square(i) + " "); // 1 4 9
Console.WriteLine();

述語を動的に構築する

一般的な用途の 1 つは、ユーザー入力から実行時にフィルター述語を構築し、それを Func にコンパイルすることです。

using System;
using System.Linq.Expressions;

var n = Expression.Parameter(typeof(int), "n");
var isPositive = Expression.GreaterThan(n, Expression.Constant(0));
var pred = Expression.Lambda<Func<int, bool>>(isPositive, n).Compile();
Console.WriteLine(pred(5));  // True
Console.WriteLine(pred(-2)); // False

条件を組み合わせる

コンパイル前に Expression.AndAlso / OrElse を使って述語を組み合わせます。

using System;
using System.Linq.Expressions;

var n = Expression.Parameter(typeof(int), "n");
var inRange = Expression.AndAlso(
    Expression.GreaterThanOrEqual(n, Expression.Constant(1)),
    Expression.LessThanOrEqual(n, Expression.Constant(10)));
var fn = Expression.Lambda<Func<int, bool>>(inRange, n).Compile();
Console.WriteLine(fn(5) + " " + fn(11)); // True False

計算式をコンパイルする

実行時に算術式を組み立てることもできます。これはルールエンジンや計算機に役立ちます。

using System;
using System.Linq.Expressions;

var p = Expression.Parameter(typeof(double), "p");
// price * 1.2 (add 20% tax)
var withTax = Expression.Multiply(p, Expression.Constant(1.2));
var calc = Expression.Lambda<Func<double, double>>(withTax, p).Compile();
Console.WriteLine(calc(100)); // 120

型指定のないラムダ式に DynamicInvoke を使う

ジェネリックではない Expression.Lambda を使用した場合は、Delegate にコンパイルして DynamicInvoke を呼び出します。

using System;
using System.Linq.Expressions;

var x = Expression.Parameter(typeof(int), "x");
var body = Expression.Add(x, Expression.Constant(10));
Delegate d = Expression.Lambda(body, x).Compile();
Console.WriteLine(d.DynamicInvoke(5)); // 15

パフォーマンスに関する注意

コンパイル済みの式は、1 回コンパイルした後はおおむねデリゲートと同じ速度で実行されます。頻繁に実行される処理では、起動時に 1 回だけコンパイルしてデリゲートを保存してください。

using System;
using System.Linq.Expressions;

Expression<Func<int, int>> tree = x => x + x;
var doubler = tree.Compile();
int total = 0;
for (int i = 0; i < 5; i++) total += doubler(i);
Console.WriteLine(total); // 0+2+4+6+8 = 20

コンパイル時にエラーが表面化する

ツリーの形式が不正な場合(パラメーターが不足している場合など)、Compile() は例外をスローします。そのため、ツリーを利用する前に検証してください。

using System;
using System.Linq.Expressions;

var x = Expression.Parameter(typeof(int), "x");
var y = Expression.Parameter(typeof(int), "y");
try {
    // body references y but lambda only declares x
    var lambda = Expression.Lambda<Func<int, int>>(Expression.Add(x, y), x);
    lambda.Compile();
} catch (InvalidOperationException) {
    Console.WriteLine("unbound parameter");
}

まとめ

小さな計算式を 1 つの流れで構築、コンパイル、実行します。

using System;
using System.Linq.Expressions;

var x = Expression.Parameter(typeof(int), "x");
var formula = Expression.Add(
    Expression.Multiply(x, Expression.Constant(2)),
    Expression.Constant(3)); // 2x + 3
var fn = Expression.Lambda<Func<int, int>>(formula, x).Compile();
Console.WriteLine(fn(4)); // 11

クイックチェック

式ツリーを実行する方法を確認します。

まとめ

式ツリーをコンパイルして実行する方法を学びました。

  • Compile() は、ツリーを呼び出し可能なデリゲートに変換します。
  • コンパイルには 1 回限りのコストがかかるため、デリゲートをキャッシュします。
  • 述語や計算式を動的に構築してからコンパイルできます。
  • 形式が不正なツリーは Compile() で例外をスローします。

よくある質問

「式のコンパイルと実行」レッスンは無料ですか?

はい。「式のコンパイルと実行」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。

「式のコンパイルと実行」で何を学びますか?

式ツリーを実行可能なデリゲートに変換します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C# Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「式のコンパイルと実行」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC# Academyレッスンでコードを書いて実行できますか?

はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 式ツリーとは
  2. 式の手動構築
  3. 式のコンパイルと実行
  4. LINQプロバイダーにおける式ツリー
← C# Academyに戻る