今回はC#でデリゲートとラムダ式を使ってみようと思います。
Unityでゲームを作る上で今まで使ってきませんでしたが・・・(^_^;)
今回は勉強してみましょう。
今回のサンプルもUnity付属のMonoDevelopを使って確認します。
デリゲートとラムダ式はあんまり馴染みがないのでとりあえずの使い方といった感じになります。
Unity関連の記事でデリゲートやラムダ式を使うと解り辛くなると思うので(自分的にも)、必要に迫られない限りは使わないと思います。
デリゲートについて詳しく知りたい方は
ラムダ式については
のC#ガイドをご覧ください。
デリゲート
デリゲートを使うと、メソッドの引数としてデリゲートに登録したメソッドを渡す事が出来ます。
例えばint型の配列にいくつかの数値が入っていて、その中から条件に合致する値だけを足したい!
といった時に変数をカウントするメソッドに条件に合致しているかどうかを判断するメソッドも引数として渡す事が出来ます。
文章だけではわからないのでサンプルを作成しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | using UnityEngine; using System.Collections; public class Learn6_1 : MonoBehaviour { // デリゲートを宣言 public delegate bool DelegateMethod(float floatValue); // 合計値を入れるフィールド private float sum = 0; // Use this for initialization void Start () { // float型の配列宣言 float[] floatValues = new float[]{ 1.5f, -2.0f, -3.5f, 4.5f }; // DelegateMethod型の変数宣言と初期化 DelegateMethod delegateMethod1 = Check1; DelegateMethod delegateMethod2 = Check2; // 配列数分繰り返して該当する数値を数える foreach (var value in floatValues) { Count (value, delegateMethod1); } Debug.Log ("正の値の合計値は " + sum); sum = 0; // 配列数分繰り返して該当する数値を数える foreach (var value in floatValues) { Count (value, delegateMethod2); } Debug.Log ("負の値の合計値は " + sum); } // 該当する数値だけを足すCountメソッド void Count(float floatValue, DelegateMethod delegateMethod) { if (delegateMethod(floatValue)) { sum += floatValue; } } // 数値が0より上の数値かどうか bool Check1(float value) { return value > 0f; } // 数値が0より下の数値かどうか bool Check2(float value) { return value < 0f; } } |
delegateを付けたfloat型の引数を受け取りbool型の値を返すDelegateMethodデリゲートメソッドを宣言します。
Startメソッド内でint型の配列を宣言し、初期値を入れています。
DelegateMethod型のdelegateMethod1とdelegateMethod2を宣言し、それぞれCheck1とCheck2メソッドを代入しています。
つまり、引数としてdelegateMethod1とdelegateMethod2を指定するとCheck1とCheck2メソッドが渡されることになります。
Check1は受け取った引数が0より上の数値だったらtrue、それ以外はfalseを返します。
Check2は受け取った引数が0より下の数値だったらtrue、それ以外はfalseを返します。
foreach文でint型配列のintValues数回繰り返し、Countメソッドに要素のfloat値とデリゲートのdelegateMethod1を渡します。
Countメソッドでは受け取ったデリゲートに受け取ったfloat値を渡して判定し、trueが返ってくれば値を足しています。
つまり受け取ったデリゲートの処理に応じてどんな数値をsumに渡すかが変わってきます。
それを確認したのが、下のCountメソッドでdelegateMethod2を渡している部分です。
やっている事は同じですが、渡すデリゲートが違う為に違う結果が得られます。
ラムダ式
デリゲートは宣言やらメソッドの設定やらがややこしいですね、後はデリゲート用に別途メソッドを用意しなくてはいけないのも面倒くさいです。
匿名メソッドを利用する事も出来ますが、ラムダ式を使うとシンプルな記述が可能です。
ラムダ式はデリゲートを引数として渡していた部分に式を記述し、それを直接渡します。
先ほどのスクリプトを書き換えてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | using UnityEngine; using System.Collections; using System.Xml.Linq; using System; public class Learn6_2 : MonoBehaviour { // Use this for initialization void Start () { // float型の配列宣言 float[] floatValues = new float[]{ 1.5f, -2.0f, -3.5f, 4.5f }; float sum = Count (floatValues, x => x > 0); Debug.Log ("正の数の合計値 " + sum); sum = Count (floatValues, x => x < 0); Debug.Log ("負の数の合計値 " + sum); } float Count(float[] floatValues, Predicate<float> delegateMethod) { float tempSum = 0f; foreach (var value in floatValues) { if (delegateMethod(value)) { tempSum += value; } } return tempSum; } } |
デリゲートの宣言や初期化が不要になり、デリゲート用のメソッドであったCheck1、Check2も必要なくなります。
1 2 3 | float sum = Count (floatValues, x => x > 0); |
の第2引数でラムダ式を渡しています。
仮の変数であるxを宣言し、そのxがどの条件の時かを右辺で指定します。
変数は複数使用する場合は(x, y)のように小括弧が必要になります。
Countメソッドではfloat型の値を扱うPredicateデリゲートを受け取ります。
それを使って要素を足して戻り値を返しています。
先ほど作ったデリゲート版と同じ結果が得られますが、記述がシンプルになっていますね。
終わりに
正直なところデリゲートやラムダ式は苦手です。(^_^;)
使いなれてないからかもしれませんが・・・。
このラムダ式を使うとリストのメソッドの引数として渡したり、LINQを使う時の引数として渡したりして結構活躍します。
使いたくはないけど使わざるを得なくなりますね・・・・( ノД`)シクシク…