Theme
SD MILIEU

2018-5-19

delegate/Action/event/UnityAction/UnityEvent

delegate

変数に関数を格納するために、関数の型を定義するための方法。

例えば、

delegate void OnCalcComplete(float value);

これは、「float 型の引数を持ち void を返す OnCalcComplete という型の関数」を定義している。

delegate void OnCalcComplete(float value);

class MyDelegate
{
    public void Calc(OnCalcComplete callback)
    {
        // 計算
        var result = 1.0f * 100.0f;

        callback(result);
    }
}

class Program
{
    static void Main(string[] args)
    {
        var myDelegate = new MyDelegate();
        myDelegate.Calc(PrintValue);
    }

    static void PrintValue(float value)
    {
        Console.WriteLine(value);
    }

}

delegate によって上のように、関数を渡して実行させることが可能。

ちなみに delegate は+=演算子で実行する関数を追加していくことが出来るマルチキャストデリゲートという機能がある。これは主に後述するeventにて使う。

Action

Action は delegate をもっと楽に書くための方法と思えばいい。

Action を使用すると、前述のソースは以下のようになる。

class MyDelegate
{
    public void Calc(Action<float> callback)
    {
        // 計算
        var result = 1.0f * 100.0f;

        callback(result);
    }
}

class Program
{
    static void Main(string[] args)
    {
        var myDelegate = new MyDelegate();
        myDelegate.Calc(PrintValue);
    }

    static void PrintValue(float value)
    {
        Console.WriteLine(value);
    }

}

delegate ~の行を削除し、OnCalcCompleteAction<float>にて置き換えている。

OnCalcCompleteはつまり「float を引数として持ち、返り値が無い関数」を表すための型だが、わざわざ毎回自前で命名するのは面倒だからそういう場合はAction<T>を使って汎用的に表現しろって話。

ちなみに、Action は戻り値が無い場合に使い、戻り値がある場合はFuncを使う。他にも比較の際に使う Comparison 等あるけどとりあえず Action/Func を覚えとけばいいのではなかろうか。

event

ブラウザ JS におけるAddEventListenerみたいに使うためのアレ。

コード例を挙げると以下のようなもの。

class MyDelegate
{
    public event Action<float> OnCalcComplete = value => { };

    public void Calc()
    {
        // 計算
        var result = 1.0f * 100.0f;

        this.OnCalcComplete(result);
    }
}

class Program
{
    static void Main(string[] args)
    {
        var myDelegate = new MyDelegate();
        myDelegate.OnCalcComplete += value =>
        {
            Console.WriteLine(value);
        };
        myDelegate.Calc();
    }
}

やってることは delegate と同じで、実際eventを外しても動作する。

eventを付与した場合は、クラス外部からは+=-=の操作しか出来なくすることが出来る。制限をかけるためのもの。

UnityAction/UnityEvent

【Unity】UnityEvent の用法と用量 - うら干物書き

インスペクタ経由でコールバックを設定したい場合は UnityEvent を使用する、という理解で OK。詳細は上記リンクで