自分用の学習メモです。
既に多くの人が書いている内容なので、僕の記事を読むよりも他の人の記事読んだ方がいいかも... (参考サイトに飛べばわかる)
動機
現在、取り組んでいるドイツのHarz大学との合同ゲームプロジェクトにてゲームを作る上でせっかくなので設計を頑張ってみようと思いました。
ちゃんとした設計をするのは初めてだったので色々と調査をしました。
調査を進める中でUniRxというライブラリを使うと良いということを知りました。これを使ってみたいと思いました。が、その解説の中でDelegate、Eventという知らない概念があったので、それについて調べました。(ついでラムダ式、Action、匿名関数も勉強した)
Delegateとは(概念部分)
C#入門者を苦しめるDelegate、Action、Event、ラムダ式、匿名関数は全てDelegateの派生形です。なのでまずDelegateをわかるようにするのが大切。
Delegateは関数型志向の考え方をプログラムとして実現するための機能です。
関数型志向とは「関数をまとめて変数として扱おうゼ!!」という発想のことです。
delegateの書き方
delegateの使い方
よくあるのはコールバックで処理が終わった後に何かしらのメソッドを実行したいときにメソッドごと渡すというパターンです。
他にもメソッドの中身をごっそりと変えるということもできる(てことは、Strategyパターン?)
delegateの記法
1.まずCのプロトタイプ関数宣言のように書く
publicdelegatevoidDelVoid();publicdelegateintDelInt(inta);publicdelegatestringDelStr(strings);
注)ここではあくまで型を作っただけ(structやenumのような新しい型を作るのがdelegate)
2.実際にdelegateを利用して処理する部分を書く
voidMethod1(DelVoiddelvoid){//処理delvoid();}voidMethod2(DelIntdelint){//処理delint();}voidMethod3(DelStrdelstr){//処理delstr();}
ここまでで型の定義とその型を持つ変数の使い方が決まった
外部からの使い方
1.delegate変数の中身を代入
クラス名.DelVoid.delvoid=A;クラス名.DelInt.delint=B;クラス名.Delstr.delstr=C;
とすることでMethod1,2,3のdelegete系変数の中身を宣言できる(A、B、Cはそれぞれの型と一致する引数と戻り値を持つ関数)
クラス名の部分にはDelVoidを型宣言したクラス名を書く
2.delegateを使う
クラス名.Method1(delvoid);クラス名.Method2(delint);クラス名.Method3(delstr);
これで先ほど代入したA,B,Cの内容をMethod1,2,3内で線芸している箇所に貼り付けて使うことができます。
Action
Actionはdelegateの省略表現
Action<引数の型>action=A
のように書く。引数は<string,int>のように「,」で区切ることで複数渡せる
引数がない場合は
Action action = A
でおk
要はActionによって明示的な名前(DelVoidのようなやつ)をつけずに引数と戻り値だけで判断することができる
ただし、Actionは戻り値を返すことができないvoid関数しか作れない
戻り値を返したい場合はFuncを使う
書き方は以下の通り
Func<引数の型(複数可),戻り値> func
例えば
Func<int, string > func
は
stringfunc(intnum){//処理 //最後にstringを返す}
のような関数のdelegateとなる
引数がない場合は以下のように書く
Func<戻り値> func
例えば、
Func<int> func
は
intfunc(){//処理//最後にintを返す}
という関数のdelegateとなる
匿名関数
今までAction action = Aと書いていた
これは別にメソッドAを書かなければいけないのでめんどいし、場合によっては可読性が落ちる
これを
Action<int,string>action=delegate(intx,stringstr){//処理}
と書き換えることができる。それだけ
ラムダ式
1行だけの処理であれば、delegate、Actionをより簡単に書ける
以下のように書く
Action<引数の型> = 引数の変数名 => 処理;
他にも様々な記法があるが、一番簡潔なものを覚えておけば、とりあえずは使える。必要に応じて調べればおk
Event
ほぼdelegateと同じ
違いは外からの代入と実行ができないこと
Delegateとの使い分けは「その関数型変数を内部でしか使わないように限定するかどうか」ということ(カプセル化するかどうかってことか?)
カプセル化する場合はEvent
そうでない場合(interface的な時?)はDelegate
と覚えておけばとりあえず丸い(多分他にも細かい違いがあると思うけど、今は無視!!)
宣言の仕方
例1
publiceventActionaction=null;
例2
publiceventAction<int>action=num=>{Debug.Log("入力されたのは"+num+"です")};
外部クラスからのアクセス
エラーの例
クラス名.action();
クラス名.action = A
これは外部でdelegateを実行しようとしたり、代入しているのでNG
大丈夫な例
クラス名.action+=A
外からdelegateに処理を付け加えるのはセーフ
まとめ
delegateだけわかってればとりあえずはこの辺の概念はふわっとわかるようになる!!
参考
1.http://kan-kikuchi.hatenablog.com/entry/Delegate
2.https://qiita.com/RyotaMurohoshi/items/740151bd772889cf07de
3.https://hk-ryukyu.club/hideto/archives/49#toc6