C#におけるデリゲート(Delegate)の完全かつ包括的な解説
C#のデリゲートは、メソッドの参照を格納し、それを他の場所で呼び出すための型安全なオブジェクトです。デリゲートを理解することは、C#のプログラミングにおいて非常に重要です。特に、イベント駆動型プログラミングやコールバック関数、LINQのような操作で広く使用されており、非常に強力なツールとなります。本記事では、デリゲートの基本的な概念から応用的な使用方法までを、豊富な例を交えて説明します。
1. デリゲートの基本
デリゲートは、メソッドのシグネチャを持つ型であり、その型に一致するメソッドを参照できます。つまり、デリゲートはメソッドを引数として受け取ったり、返したりできる、関数ポインタのようなものです。

デリゲートの宣言
デリゲートを定義するには、delegate
キーワードを使用します。基本的な構文は次のようになります。
csharpdelegate 戻り値の型 デリゲート名(引数の型 引数名);
例えば、int
型の引数を1つ取り、void
を返すデリゲートは次のように宣言します。
csharpdelegate void MyDelegate(int x);
デリゲートの使用例
デリゲートを使用するためには、まずその型に一致するメソッドを定義します。次に、そのメソッドをデリゲートに割り当て、デリゲートを使ってメソッドを呼び出します。
csharpusing System;
class Program
{
// デリゲートの定義
delegate void MyDelegate(int x);
// メソッドの定義
static void PrintNumber(int x)
{
Console.WriteLine($"Number: {x}");
}
static void Main()
{
// デリゲートのインスタンスを作成し、メソッドを割り当てる
MyDelegate del = new MyDelegate(PrintNumber);
// デリゲートを使ってメソッドを呼び出す
del(5); // 出力: Number: 5
}
}
このコードでは、PrintNumber
メソッドをデリゲートMyDelegate
に割り当て、del(5)
によって呼び出しています。
2. デリゲートの型安全性
デリゲートは型安全であるため、デリゲートに一致しないメソッドを割り当てようとするとコンパイルエラーが発生します。例えば、以下のように戻り値の型や引数が異なる場合にはエラーが発生します。
csharp// このコードはコンパイルエラーとなります
delegate void MyDelegate(int x);
void WrongMethod(string str)
{
Console.WriteLine(str);
}
MyDelegate del = new MyDelegate(WrongMethod); // コンパイルエラー
このように、デリゲートは呼び出すメソッドのシグネチャと一致していない場合、エラーとなります。
3. 複数メソッドの登録(マルチキャストデリゲート)
デリゲートは、複数のメソッドを同時に呼び出すことができます。この機能を「マルチキャストデリゲート」と呼びます。複数のメソッドをデリゲートに登録するには、+
演算子を使います。
csharpusing System;
class Program
{
delegate void MyDelegate(int x);
static void PrintA(int x)
{
Console.WriteLine($"A: {x}");
}
static void PrintB(int x)
{
Console.WriteLine($"B: {x}");
}
static void Main()
{
MyDelegate del = PrintA;
del += PrintB; // PrintBを登録
// 両方のメソッドが呼び出される
del(5); // 出力: A: 5
// 出力: B: 5
}
}
この例では、PrintA
とPrintB
という2つのメソッドをデリゲートに登録し、del(5)
が実行されると、両方のメソッドが順番に呼び出されます。
4. デリゲートの戻り値
デリゲートには戻り値を設定することもできます。例えば、int
型の戻り値を持つデリゲートを使って、いくつかの計算を順番に行うことができます。
csharpusing System;
class Program
{
delegate int Calculate(int x, int y);
static int Add(int x, int y)
{
return x + y;
}
static int Multiply(int x, int y)
{
return x * y;
}
static void Main()
{
Calculate calc = Add;
calc += Multiply; // Multiplyも登録
// 両方のメソッドを呼び出す
int result = calc(2, 3); // AddとMultiplyが呼び出される
Console.WriteLine(result); // 結果はMultiplyが最後に実行されるので、結果は6 (2 * 3)
}
}
上記の例では、Add
とMultiply
メソッドをデリゲートに登録しており、デリゲートの最終的な戻り値はMultiply
メソッドによって計算されたものになります。
5. デリゲートの応用
デリゲートは、非常に多くの実用的な用途があります。特に、イベント駆動型プログラミングやコールバック機構でよく使用されます。
イベントの利用
C#のイベントは、デリゲートを基にしています。イベントはデリゲートによってメソッドが登録され、何らかのアクションが発生した際に、そのアクションに関連するメソッドが呼び出される仕組みです。
csharpusing System;
class Program
{
// デリゲートの定義
delegate void Notify();
// イベントの定義
static event Notify OnNotify;
static void Main()
{
// イベントにメソッドを登録
OnNotify += () => Console.WriteLine("通知が届きました!");
// イベントを発火
OnNotify?.Invoke(); // 出力: 通知が届きました!
}
}
このコードでは、OnNotify
イベントにメソッドを登録し、OnNotify.Invoke()
でイベントを発火させています。
6. 匿名メソッドとラムダ式
デリゲートは、匿名メソッドやラムダ式とも一緒に使うことができます。これにより、簡潔で柔軟なコードを書くことが可能になります。
匿名メソッド
csharpusing System;
class Program
{
delegate void MyDelegate(int x);
static void Main()
{
MyDelegate del = delegate (int x) {
Console.WriteLine($"匿名メソッドで受け取った値: {x}");
};
del(5); // 出力: 匿名メソッドで受け取った値: 5
}
}
ラムダ式
ラムダ式は、さらに簡潔にデリゲートを定義できる方法です。
csharpusing System;
class Program
{
delegate void MyDelegate(int x);
static void Main()
{
MyDelegate del = (x) => Console.WriteLine($"ラムダ式で受け取った値: {x}");
del(10); // 出力: ラムダ式で受け取った値: 10
}
}
ラムダ式を使うと、デリゲートを宣言する際に非常に短いコードで済み、可読性が向上します。
7. デリゲートのまとめ
C#のデリゲートは、メソッドをオブジェクトとして扱うための非常に強力なツールです。型安全であり、イベント駆動型プログラミングやコールバック、マルチキャスト、匿名メソッド、ラムダ式など、さまざまなシナリオで利用できます。デリゲートをうまく使いこなすことで、柔軟で拡張性の高いプログラムを作成することができます。
デリゲートは、イベントハンドリングや非同期処理などの高度な概念を学ぶ上で基盤となる重要な要素です。理解しておくと、C#プログラムの構築において非常に役立つでしょう。