WPF_Delegateとコールバック操作

delegate

デリゲートとは

C#のデリゲートは、関数を入れることができる変数(データ型)です。


delegate 戻り値の型 デリゲート型名(引数リスト);

代入することでメソッドを割り当てます。


using System;

namespace LogicTest
{
    class Program
    {
        public delegate void Deleg(String str);

        static void Main(string[] args)
        {
            // Deleg1にメソッド execute1 を割り当てる
            Deleg Deleg1 = new Deleg(execute1);

            // Deleg1を実行することで、実際には execute1 が実行される
            Deleg1("Deleg1");

            // メソッドはnewなしでも割り当てられる
            Deleg Deleg2 = execute1;
            Deleg2("Deleg2");

            // 複数メソッドを割り当てることができます
            Deleg2 += new Deleg(execute2);
            Deleg2("Deleg2");
        }

        public void execute1(string str1)
        {
            System.Console.WriteLine("execute1() is called by " + str1);
        }

        public void execute2(string str1)
        {
            System.Console.WriteLine("execute2() is called by " + str1);
        }
    }
}

コールバック処理

delegateにメソッドを代入して、処理完了の契機でコールバックメソッドを実行することは、頻繁に利用する手法です。


public delegate void Callback(string msg);

public void Main(string[] args)
{
    Execute(OutputMessage);
}

public void Execute(Callback callback)
{
    System.Console.WriteLine("Execute(): start");
    Thread.Sleep(2000);

    callback("Execute callback!");

    System.Console.WriteLine("Execute(): finish");
}

public void OutputMessage(string msg)
{
    System.Console.WriteLine("OutputMessage(): " + msg);
 }

FuncとAction

FuncとActionの違い

デリゲートの形式をいちいち宣言することが手間である場合、Func/Actionが利用できます。

Funcは下記のように定義した場合、delegateMethodに「intの引数を1つとり、intの値を返す」処理を登録することができます。


Func<int, int> delegateMethod

Actionは下記のように定義した場合、delegateMethodに「int 型の引数を2つとる」処理を登録することができます。


Action<int, int> delegateMethod

簡単にいえば、返り値が無い場合がAction、返り値が有る場合が Funcです。


//引数がstring
Action<string> action1;

//引数がstringとint
Action<string, int> action2;

//返り値がint
Func<int> func1;

//引数がstring、返り値がint
Func<string, int> func2;

Funcのコールバック処理例

メソッドの引数にコールバックメソッドをセットし、任意に実行します。


public void Main(string[] args)
{
    bool rc = Execute(OutputMessage);
}

public bool Execute(Func<string, bool> callback)
{
    System.Console.WriteLine("Execute(): start");
    Thread.Sleep(2000);

    // コールバックを実行する。
    bool rc = callback("Execute callback!");

    System.Console.WriteLine("Execute(): finish");
    return rc;
}

public bool OutputMessage(string msg)
{
    try
    {
        System.Console.WriteLine("OutputMessage(): " + msg);
        return true;
    }
    catch (Exception ex)
    {
        System.Console.WriteLine(ex.Message);
        return false;
    }
}

event

eventは、delegate専用の修飾語になります。

eventキーワードを使用すると、外部から代入と実行はできなくなります。

「これ使って」と渡すのがDelegateであり、「こちらで使うから登録して」とするのがEventとなります。


class MyClass
{
    public       Action<string> Delegate; // delegate
    public event Action<string> Event;    // event

    // Event実行用の公開メソッド
    public void ExecEventMethod(string txt)
    {
        // 下記の記載で if (Event != null) { Event(txt); }と同じ意味となる。
        Event?.Invoke(txt);
    }
}

private void WriteMsg(string msg)
{
    BindText += msg;
    BindText += Environment.NewLine;
}

public void Main()
{
    var my = new MyClass();

    // delegateの場合
    my.Delegate = WriteMsg;
    my.Delegate += WriteMsg;
    my.Delegate -= WriteMsg;
    my.Delegate("Execute Delegate Method");

    // eventの場合
    // my.Event = WriteMsg; // エラー
    my.Event += WriteMsg;
    my.Event -= WriteMsg;
    //my.Event("Execute Event Method"); // エラー

    // eventの登録メソッドを実行する場合は、MyClassから呼び出す口を用意する。
    my.Event += WriteMsg;
    my.ExecEventMethod("Execute Event Method");
}

関連ページ