はじめに
Unityのスクリプトを読んでいると下記の見慣れないコードに出会いました。
public event Action<string> Hogehoge;
このコードの理解に大分時間を要したため、勉強の手順を残しておきます。
手順
- 1.Delegate
- 2.Action
- 3.匿名メソッド
- 4.ラムダ式で書き換え
- 5.Event
Delegate(デリゲート)
はじめに、デリゲートとは、
関数を入れられる変数
というイメージです。
delegateMethod += Method;
右のMethodメソッド(関数)を左のデリゲートに渡しています。
次に、デリゲートでよく使われるコールバックの仕組みについて見ていきます。
コールバックとは、
処理後に指定のメソッドを呼び出す方法
です。
まずは、デリゲートの作成とデリゲートを実行するメソッドを作成します。
public class Practice { //デリゲートの作成 public delegate void Dele(); //処理①後、入力されたデリゲート(deleMethod)を実行する public void Method(Dele deleMethod){ //処理① deleMethod(); } }
上記で着目してほしいところは、
「deleMethod」
です。practiceクラスの内容では、deleMethodに関数がなにも渡されていない状態です。
では、deleMethodに関数を渡してみましょう。
public class Practice1 { //Practice(デリゲートを作成したクラス)を作成しMethodを実行する public void Method(){ Practice practice = new Practice(); //PracticeクラスのMethodメソッドの引数に使用するDele deleMethodにAメソッドを渡している Practice.Dele deleMethod = A; test2.Method(deleMethod); } //Practiceの処理が終わったら呼ばれる public void A(){ Debug.Log("処理完了"); } }
ここで、着目してほしいところは、
Practice.Dele deleMethod = A;
この記述で、先ほどのdeleMethodにAという関数を渡しています。
もう一度、Practiceクラスを見てみましょう。
public class Practice { public delegate void Dele(); public void Method(Dele deleMethod){ //処理① deleMethod(); //ここでAメソッドが呼ばれる } }
これで、処理①が完了後にAメソッドが呼ばれるようになりました。
デリゲートでは、複数のメソッドを渡すこともできます。
つまり、
A、B、Cメソッドを処理①後に呼び出すことができます。
では、複数のメソッドを渡す方法を見ていきます。
public void Method(){ Practice practice = new Practice(); Practice.Dele deleMethod = A; Practice.Dele deleMethod += B; Practice.Dele deleMethod += C; Practice.Method(deleMethod); } public void A(){ Debug.Log("処理完了"); } public void B(){ Debug.Log("処理完了B"); } public void C(){ Debug.Log("処理完了C"); } }
ここで、着目してほしいところは、
Practice.Dele deleMethod += B;
「=」ではなく、
「+=」演算子を使用しています。
これで、PracticeクラスのMethodメソッドの処理①後に、
メソッドA、B、Cが呼ばれるようになりました。
Action
Actionは、以前のコードを省略して書く方法という印象です。
では、どのように省略されているのか以前のコードと比較して見てみましょう。
まずは、以前のデリゲートのコード
public class Practice { public delegate void Dele(); public void Method(Dele deleMethod){ //処理① deleMethod(); } }
Actionを使用した場合、
Public class Practice{ public void Method(Action deleMethod){ //①処理 deleMethod(); } }
「public delegate void Dele();」が省略されています。また、
「public void Method(Action deleMethod)」
Methodの引数の一部がActionに置き換わっています。
次に、Actionを使用した場合のdeleMethodに関数を渡す方法を見てみましょう。
Action deleMethod = A; deleMethod += B; deleMethod += C;
以前の「Practice.Dele deleMethod = A;」と比べると、簡潔に書かれているのが分かります。
引数を設定する場合はこのようになります。
Action<string> deleMethod = A;
Actionを使用することで、より簡潔にコードを書くことができました。
匿名メソッド
匿名メソッドを一言でいうと、「その場でメソッド作れますよ」です。
まず、今までの、関数をデリゲートに渡すコードを見てみます。
Action deleMethod = A;
これだと、Aメソッドを別で作成しなければいけません(めんどくさい)
匿名メソッドを使うとその場でメソッドを作成することができます↓
Action deleMethod = delegate { Debug.Log("処理完了"); };
引数がある場合は↓
Action<string, int> deleMethod = delegate(string A, int B) { Debug.Log("処理完了"); };
メソッド名が、
delegateに置き換わった
と考えれば、難しくないですね。
ラムダ式で書き換え
これまでのコードをさらに、簡潔に書くために、ラムダ式を使います。
これまでのコードとラムダ式を使用した場合のコードを比較してみましょう。
以前のコード↓
Action deleMethod = delegate { Debug.Log("処理完了"); };
ラムダ式使用コード↓
Action deleMethod = () => Debug.Log("処理完了");
コードの後半部分がより簡潔になっていることが分かります。
引数を設定する場合は、()の中に書き込むだけです。↓
Action deleMethod = (string,int) => Debug.Log("処理完了");
ラムダ式を使用することで、
デリゲートに関数を渡す方法がより簡潔になりました。
Event
Eventは、デリゲートと似ていますが、わずかに違うところもあるので、相違点に着目して見てみましょう。
まず、Eventが使用されている、コードを見てみます↓
public class Practice1{ public void Method(){ Practice practice = new Practice(); practice.A += () => Debug.Log("処理完了"); practice.Method(); } } public class Practice{ public event Action A = null; public void Method(){ //処理 if(A != null){ A(); } } }
まず、Practiceクラスを細かく分けて見てみます。
public event Action A = null;
Aにnullが代入されています。Aに空を代入したということですね。↑
public void Method(){ //処理 if(A != null){ A(); } }
メソッドの内容を見ると、処理後に、
Aになにかしら入っていれば、Aに追加されているメソッドを実行するという内容になっています。
では、Aには、どのようにメソッドを追加しているのでしょうか?
Practice1クラスを細かく分けて、見てみましょう。
public void Method(){ Practice practice = new Practice();
ここまでは、今まで通りですね↑
practice.A += () => Debug.Log("処理完了");
こちらで、Aにラムダ式でメソッドを追加しています↑
つまり、処理後にDebug.Log(“処理完了”)が行われるわけですね。
practice.Method();
最後は、今まで通りですね↑
次に、Eventの機能についてみていきます。
Eventがついた変数は、
外部から実行と代入はできません。
コードで見てみますと、
public class Practice1{ public void Method(){ Practice practice = new Practice(); //practice.A(); エラー //practice.A = () => Debug.Log("処理完了"); エラー practice.Method(); } }
このように、Practiceクラスで設定したEventは他のクラスでの、実行、代入ができません。
参考文献

コメント