イベント処理やコールバックが簡単になるらしいdelegate。わかる単語が一つもないのでdelegateから順々に調べていきたいと思います。
delegateとは
delegateは、メソッドへの参照を表す型です。
delegateの最大の特徴は、メソッドを引数として扱ったり、複数のメソッドを一度に呼び出したりできます。
使い方
定義から具体的な例まで書いていきます。
定義の仕方
delegateを使うにはまず以下の形で宣言します。
delegate 引数の型 delegate型名 戻り値の型
例えば、delegate void MyDelegate(int value);は、int型の引数をとり、戻り値がないメソッドを参照できるdelegateです。
インスタンス化する
次に既存のメソッドを指定してインスタンス化します。
void MyMethod(int value)
{
// メソッドの処理
}
MyDelegate myDelegate = new MyDelegate(MyMethod);
呼び出す
最後に呼び出します。
myDelegate(10);
ここまでのまとめ
今までのをまとめるとこうなります。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DelegateExample : MonoBehaviour
{
delegate void MyDelegate(int value); //delegateの定義
void MyMethod(int value)
{
Debug.Log(value);// メソッドの処理
}
void Start()
{
MyDelegate myDelegate = new MyDelegate(MyMethod); //インスタンス化
myDelegate(10); //呼び出し
}
}
適当なオブジェクトにスクリプトをアタッチしたらちゃんとログが出ます。
10
UnityEngine.Debug:Log (object)
ここまでやってみて
さて、ここまでやってみて基本的なことは分かりました。しかし一つ思うことがあります。
delegate挟まなくても指定したメソッドを直接呼び出せばばよくね?
確かにここまで別にdelegateを使う意味は全くないように感じます。
ですがここからdelegateを使うメリットを紹介します。
delegateを使う利点
複数のメソッド呼び出しが簡単にできる
以下に複数のメソッドを扱うスクリプトを載せます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DelegateExample : MonoBehaviour
{
delegate void MyDelegate(string message); //Delegateの定義
private void Start()
{
// Delegateのインスタンス化
MyDelegate myDelegate = new MyDelegate(PrintMessage);
// Delegateの呼び出し
myDelegate("Hello, World!");
// Delegateにメソッドを追加
myDelegate += ShowMessage;
// Delegateの呼び出し(複数のメソッドが呼び出される)
myDelegate("Welcome!");
// Delegateからメソッドを削除
myDelegate -= ShowMessage;
// Delegateの呼び出し(削除されたメソッドは呼び出されない)
myDelegate("Goodbye!");
}
private void PrintMessage(string message)
{
Debug.Log("Print: " + message);
}
private void ShowMessage(string message)
{
Debug.Log("Show: " + message);
}
}
DelegateExample
クラスにMyDelegate
を宣言し、それを使用して2つのメソッドを呼び出しています。Start
メソッド内で、myDelegate
にメソッドを追加したり削除を行っています。
以下が実行したときのログです。
Print: Hello, World!
Print: Welcome!
Show: Welcome!
Print: Goodbye!
複数のメソッドを簡単に呼び出したり、削除したりできるのはdeligateを使う大きな利点です。
FunctionとActionを使った定義の省略
今までdeligateを使うときは
delegate 引数の型 delegate型名 戻り値の型
で定義していましたが、ActionとFunctionを使うことで省略することができます。
ActionとFunctionは関数を参照する型です。
Actionを使って定義を省略してみます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DelegateExample : MonoBehaviour
{
delegate void MyDelegate(int value); //delegateの定義
void MyMethod(int value)
{
Debug.Log(value);// メソッドの処理
}
void Start()
{
MyDelegate myDelegate = new MyDelegate(MyMethod); //インスタンス化
myDelegate(10); //呼び出し
}
}
Actionなし
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System; //Actionを使うために追加
public class DelegateExample : MonoBehaviour
{
//定義の削除
void MyMethod(int value)
{
Debug.Log(value); // メソッドの処理
}
void Start()
{
// Actionデリゲートのインスタンス化
// 引数としてint型の値を受け取り、戻り値はなし
Action<int> myDelegate = new Action<int>(MyMethod);
myDelegate(10); // 呼び出し
}
}
Actionあり
Actionは戻り値なし、Functionは戻り値ありです。
今回は元が戻り値なしだったので、Actionで実行しました。
//引数がstring
Action<string> action1;
//引数がstringとint
Action<string, int> action2;
//返り値がint
Func<int> func1;
//引数がstring、返り値がint
Func<string, int> func2;