2025年4月16日水曜日

C# におけるデリゲート (delegate) とは

 C# におけるデリゲート (delegate) とは、メソッドを参照する型です。簡単に言えば、「メソッドへの参照を保持できる変数」のようなものです。

どんな役割があるのですか?

デリゲートは、主に以下の役割を果たします。

  1. メソッドを引数として渡す: デリゲートを使うことで、メソッド自体を別のメソッドの引数として渡すことができます。これにより、処理の内容を呼び出し元で柔軟に指定できるようになります。これは、イベントハンドリングやコールバック関数などで非常に重要です。

  2. イベント処理: C# のイベントは、デリゲートを基盤として実装されています。イベントが発生したときに、登録されたデリゲート(イベントハンドラー)が呼び出されます。

  3. コールバック関数: ある処理が完了した後に、特定のメソッドを実行したい場合に、デリゲートを使ってそのメソッドを登録しておくことができます。

  4. 処理の遅延実行: デリゲートを使ってメソッドへの参照を保持しておき、後で必要になったタイミングでそのメソッドを実行することができます。

  5. 匿名メソッドとラムダ式: デリゲートと組み合わせて、名前のないメソッド(匿名メソッド)や簡潔な記述が可能なラムダ式を利用することで、コードをより簡潔にすることができます。

どんな使い方があるのですか?

デリゲートの基本的な使い方は以下の通りです。

  1. デリゲート型の宣言: まず、どのようなシグネチャ(引数の型と戻り値の型)を持つメソッドを参照できるデリゲート型を宣言します。

    C#
    // int型の引数を1つ取り、void(何も返さない)型のメソッドを参照できるデリゲート型
    public delegate void MyDelegate(int x);
    
    // string型の引数を2つ取り、string型を返すメソッドを参照できるデリゲート型
    public delegate string StringOperation(string str1, string str2);
    
  2. デリゲート変数の作成とメソッドの割り当て: 宣言したデリゲート型の変数を作成し、それに互換性のあるシグネチャを持つメソッドを割り当てます。

    C#
    public class Example
    {
        public static void PrintNumber(int num)
        {
            Console.WriteLine($"Number: {num}");
        }
    
        public static string ConcatenateStrings(string a, string b)
        {
            return a + b;
        }
    
        public void InstanceMethod(int val)
        {
            Console.WriteLine($"Instance value: {val}");
        }
    }
    
    public class Program
    {
        public static void Main(string[] args)
        {
            // 静的メソッドをデリゲート変数に割り当てる
            MyDelegate delegate1 = Example.PrintNumber;
            StringOperation delegate2 = Example.ConcatenateStrings;
    
            Example exampleInstance = new Example();
            // インスタンスメソッドをデリゲート変数に割り当てる
            MyDelegate delegate3 = exampleInstance.InstanceMethod;
    
            // デリゲートの実行
            delegate1(10); // 出力: Number: 10
            string result = delegate2("Hello, ", "World!");
            Console.WriteLine(result); // 出力: Hello, World!
            delegate3(20); // 出力: Instance value: 20
        }
    }
    
  3. デリゲートの実行: デリゲート変数をメソッドのように呼び出すことで、割り当てられたメソッドが実行されます。

より高度な使い方 (例: イベント処理)

イベント処理では、複数のメソッドを一つのデリゲート変数に登録することができます。

C#
public delegate void EventHandler(string message);

public class EventPublisher
{
    public event EventHandler MyEvent; // EventHandler型のイベント

    public void DoSomething(string data)
    {
        Console.WriteLine($"Publisher is doing something with: {data}");
        // イベントが発生したら、登録されているすべてのハンドラーを呼び出す
        MyEvent?.Invoke($"Data processed: {data}");
    }
}

public class EventSubscriber
{
    public void HandleEvent1(string msg)
    {
        Console.WriteLine($"Subscriber 1 received: {msg}");
    }

    public void HandleEvent2(string msg)
    {
        Console.WriteLine($"Subscriber 2 received: {msg}");
    }
}

public class Program
{
    public static void Main(string[] args)
    {
        EventPublisher publisher = new EventPublisher();
        EventSubscriber subscriber = new EventSubscriber();

        // イベントハンドラーを登録
        publisher.MyEvent += subscriber.HandleEvent1;
        publisher.MyEvent += subscriber.HandleEvent2;

        // イベントを発生させる
        publisher.DoSomething("Important Data");
        // 出力:
        // Publisher is doing something with: Important Data
        // Subscriber 1 received: Data processed: Important Data
        // Subscriber 2 received: Data processed: Important Data

        // イベントハンドラーの登録解除
        publisher.MyEvent -= subscriber.HandleEvent1;

        publisher.DoSomething("Another Data");
        // 出力:
        // Publisher is doing something with: Another Data
        // Subscriber 2 received: Another Data processed: Another Data
    }
}

このように、デリゲートはC#において非常に重要な概念であり、柔軟で再利用性の高いコードを作成するために不可欠な要素です。

0 件のコメント:

コメントを投稿