前回 Unity での JavaScript と C# の違い という記事でちらっと書いたがなんだかわかりにくいので(主に自分が)ちゃんと調べて書いてみる。
Sponsored Links
デリゲート(delegate) って何?
デリゲート(delegate) とは名詞では"代表(者)、代表団、代理人、使節", 動詞では "権限を委任[委譲・委託・委嘱]する" といった意味を持つ英単語のようです。
プログラミングで用いられる delegate とは、メソッドや関数を参照するための型、らしいです。関数ポインターのようなものとか書いてある説明をよく見るが C も C++ も僕は知りません。
メソッドを変数に代入したり他のメソッドの引数に使ったりいろいろ便利っぽいです。
メソッドを代入したり追加したりする
さっそく delegate の動きを確認してみます。
02 | using System.Collections; |
04 | public class Main : MonoBehaviour { |
06 | public delegate void HogeDelegate( string a); |
10 | h = (a) => { Debug .Log(a);}; |
上記のスクリプトを動かすと、以下のように出力されます。
5 | // メソッド A は削除されてるので何も起こらない。 |
返り値 void で string 型の引数を一個取るメソッド HogeDelegate を delegate で定義しておき、HogeDelegate 型 の変数 h を宣言します。
この変数 h に対して、delegate で定義したものと同様の返り値と引数を持つメソッドを代入、追加、削除する事が可能になります。
メソッドを追加した状態で h を実行すると追加されたメソッドが実行されます。
引数の数が合わないと Delegate `Main.HogeDelegate' does not take `0' arguments とか返り値の型があわないと Cannot implicitly convert type `string' to `void' とか言われますね。
コールバック関数のように使う
delegate を使って関数を引数に取るメソッドを定義できます。
例えば以下のようなコード
03 | using System.Collections; |
05 | public class Test : MonoBehaviour { |
06 | public delegate void TestCallback( string s, float f); |
07 | public static float totalTime = 0.0f ; |
11 | totalTime += Time .deltaTime; |
14 | static public void Hoge(TestCallback Callback, string s) { |
15 | Callback(s, totalTime); |
21 | using System.Collections; |
23 | public class Main : MonoBehaviour { |
28 | Test.Hoge (Hoge, "Hoge Method" ); |
30 | Test.Hoge ((a,b) => { Debug .Log (a+ ":" +b.ToString()); }, "Lambda" ); |
33 | void Hoge( string s, float f) { |
34 | Debug .Log (s + ':' + f.ToString()); |
Test クラスに delegate 型で返り値と引数を含めたメソッドを定義し、Hoge メソッドの引数にそれを指定, Hoge メソッドの中で引数に渡された関数を実行しています。
これを適当なゲームオブジェクトにバインドして実行すると文字列と経過秒数を表示し続けます。
event
delegate 型の変数を宣言する際, アクセス修飾子に event をつけると他のオブジェクトから変数へアクセス(+= or -=)はできるが実行はできなくなります。
03 | using System.Collections; |
05 | public class Test : MonoBehaviour { |
06 | public delegate void Foo( float f); |
07 | public static event Foo f = null ; |
08 | public static float totalTime = 0.0f ; |
13 | totalTime += Time .deltaTime; |
20 | using System.Collections; |
22 | public class Main : MonoBehaviour { |
25 | Test.f += (a) => { Debug .Log ( "a:" + a.ToString()); }; |
26 | Test.f += (b) => { Debug .Log ( "b:" + b.ToString()); }; |
event をつけることで他の想定してない場所から呼ばれる事を防ぐことができます。
他の言語にはあまり無い機能だけどちゃんと動き確認すればどうにかなりますね。
コメント
[…] Unity C# でデリゲートを使用する | Lonely Mobiler […]
[…] Lonely Mobiler Unity C#でデリゲートを使用する […]