English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

C# デリゲート(Delegate)

関数をパラメータとして渡したい場合、どうすればいいですか?C#はリターン関数やイベントハンドラをどう処理しますか?答えは-デリゲート(delegate)。デリゲート(Delegate)は、特定のメソッドへの参照を持つ参照型の変数です。参照は実行時で変更できます。

デリゲートはメソッドシグネチャの定義の参照型データ型。デリゲートの変数を定義し、他のデータ型と同様に、デリゲートのシグネチャと一致する任何法を参照できる変数を定義できます。

デリゲートと一緒に作業するには、以下の三つのステップが関与します:

  1. デリゲートの宣言

  2. ターゲットメソッドの設定

  3. デリゲートの呼び出し

delegateキーワードと関数シグネチャを使用してデリゲートを宣言できます。以下のように表示されます。

  デリゲート文法

[アクセス修飾子] delegate [戻り値の型] [デリゲート名]([パラメータ])

以下では、MyDelegateという名前のデリゲートを宣言しています。

public delegate void MyDelegate(string msg);

上記では、MyDelegateを宣言しましたが、void戻り値の型と文字列パラメータ。デリゲートは、外部または内部で宣言できますが、実際には外部で宣言するのが一般的です。

デリゲートを宣言した後、ターゲットメソッドまたはlambda表現を設定する必要があります。デリゲートのオブジェクトを作成し、そのシグネチャがデリゲートのシグネチャと一致するメソッドを渡すことで、new キーワードを使用して実現できます。

public delegate void MyDelegate(string msg); // デリゲートの宣言
//ターゲットメソッドの設定
MyDelegate del = new MyDelegate(MethodA);
// または
MyDelegate del = MethodA; 
// または lambda 表現 
MyDelegate del = (string msg) =>  Console.WriteLine(msg);
// ターゲットメソッド
static void MethodA(string message)
{
    Console.WriteLine(message);
}

メソッドを直接割り当てることで、デリゲートのオブジェクトを作成することなくターゲットメソッドを設定できます。例:MyDelegate del = MethodA。

ターゲットメソッドを設定した後、Invoke()メソッドまたは()演算子を使用してデリゲートを呼び出すことができます。

del.Invoke("Hello World!");
//または 
del("Hello World!");

以下はデリゲートの完全な例です。

public delegate void MyDelegate(string msg); //デリゲートの宣言
class Program
{
    static void Main(string[] args)
    {
        MyDelegate del = ClassA.MethodA;
        del("Hello World");
        del = ClassB.MethodB;
        del("Hello World");
        del = (string msg) => Console.WriteLine("lambda式呼び出し: ") + msg);
        del("Hello World");
    }
}
class ClassA
{
    static void MethodA(string message)
    {
        Console.WriteLine("ClassA.MethodA()を呼び出しました。パラメータ: ") + message);
    }
}
class ClassB
{
    static void MethodB(string message)
    {
        Console.WriteLine("ClassB.MethodB()を呼び出しました。パラメータ: ") + message);
    }
}

以下の図はデリゲートを示しています。

C#デリゲート

デリゲートをパラメータとして渡す

メソッドは、以下のようにデリゲート型のパラメータを持つことができます。

public delegate void MyDelegate(string msg); //デリゲートの宣言
class Program
{
    static void Main(string[] args)
    {
        MyDelegate del = ClassA.MethodA;
        InvokeDelegate(del);
        del = ClassB.MethodB;
        InvokeDelegate(del);
        del = (string msg) => Console.WriteLine("lambda式呼び出し: ") + msg);
        InvokeDelegate(del);
    }
    static void InvokeDelegate(MyDelegate del) // MyDelegate型のパラメータ
    {
        del("Hello World");
    }
}
class ClassA
{
    static void MethodA(string message)
    {
        Console.WriteLine("ClassA.MethodA()を呼び出しました。パラメータ: ") + message);
    }
}
class ClassB
{
    static void MethodB(string message)
    {
        Console.WriteLine("ClassB.MethodB()を呼び出しました。パラメータ: ") + message);
    }
}

.NETでは、FuncとAction型は内蔵の汎型デリゲートであり、最も一般的なデリゲートに使用されるべきで、新しいカスタムデリゲートの作成は避けるべきです。

マルチキャストデリゲート

デリゲートは複数のメソッドを指すことができます。複数のメソッドを指すデリゲートをマルチキャストデリゲートと呼びます。+”または“+=演算子で関数を呼び出しリストに追加し、-と-=演算子で削除します。

public delegate void MyDelegate(string msg); //デリゲートの宣言
class Program
{
    static void Main(string[] args)
    {
        MyDelegate del1 = ClassA.MethodA;
        MyDelegate del2 = ClassB.MethodB;
        MyDelegate del = del1 + del2; // del1 + del2
        del("Hello World");
        MyDelegate del3 = (string msg) => Console.WriteLine("lambda式呼び出し: ") + msg);
        del +=3; // del1 + del2 + del3
        del("Hello World");
        del = del - del2; // delを削除2
        del("Hello World");
        del -=1 // delを削除1
        del("Hello World");
    }
}
class ClassA
{
    static void MethodA(string message)
    {
        Console.WriteLine("ClassA.MethodA()を呼び出しました。パラメータ: ") + message);
    }
}
class ClassB
{
    static void MethodB(string message)
    {
        Console.WriteLine("ClassB.MethodB()を呼び出しました。パラメータ: ") + message);
    }
}

加法および減法演算子は常に代入の一部として動作します:del1+=del2;delと1=del1+del2完全に等価;減法も同様です。

デリゲートが値をリターンする場合、マルチキャストデリゲートが呼び出されたときに、最後に割り当てられたターゲットメソッドの値がリターンされます。

public delegate int MyDelegate(); //デリゲートの宣言
class Program
{
    static void Main(string[] args)
    {
        MyDelegate del1 = ClassA.MethodA;
        MyDelegate del2 = ClassB.MethodB;
        MyDelegate del = del1 + del2; 
        Console.WriteLine(del());// リターン200
    }
}
class ClassA
{
    static int MethodA()
    {
        return 100;
    }
}
class ClassB
{
    static int MethodB()
    {
        return 200;
    }
}

ジェネリックデリゲート

デリゲートと同じ方法でジェネリックデリゲートを定義できますが、ジェネリックtypeパラメータやリターンタイプを使用できます。ターゲットメソッドを設定する際には、ジェネリックタイプを指定する必要があります。

例えば、以下のintとstringパラメータの汎用デリゲートを見てみましょう。

public delegate T add<T>(T param1, T param2; // ジェネリックデリゲート
class Program
{
    static void Main(string[] args)
    {
        add<int> sum = Sum;
        Console.WriteLine(sum(10, 20));
        add<string> con = Concat;
        Console.WriteLine(conct("Hello ", "World!!"));
    }
    public static int Sum(int val1, int val2)
    {
        return val1 + val2;
    }
    public static string Concat(string str1, string str2)
    {
        return str1 + str2;
    }
}

デリゲートは、イベントやアニミティメソッドの宣言にも使用されます。

 覚えるべきポイント

  1. デリゲートは、シグネチャを定義する参照型データ型です。

  2. デリゲートタイプの変数は、デリゲートと同じシグネチャを持つ任何のメソッドを参照できます。

  3. 文法:[アクセス修飾子]デリゲート[リターンタイプ] [デリゲート名]([パラメータ])([アクセス修飾子] delegate [リターンタイプ] [デリゲート名]([パラメータ]))

  4. ターゲットメソッドのシグネチャはデリゲートのシグネチャと一致する必要があります。

  5. デリゲートは通常の関数やinvoke()メソッドのように呼び出すことができます。

  6. を使用して +”または“ + =演算子で複数のメソッドをデリゲートに割り当て、「-”または“-=演算子で削除します。これはマルチキャストデリゲートと呼ばれます。

  7. マルチキャストデリゲートが値を返す場合、最後に割り当てられたターゲットメソッドから値を返します。

  8. デリゲートはC#でイベントと匿名メソッドを宣言するために使用されます。