型パラメータを持ったAction<T>
のようなデリゲートも,メソッドのパラメータに指定する事が出来ます。
(Unity 2019.4.17f1 Personal)
始めに
前回の記事で,型パラメータなしデリゲートのパラメータ化を取り上げました。
今回は,型パラメータありデリゲートのパラメータ化について御説明いたします。
型パラメータありデリゲートのパラメータ化例
「任意の処理の前後にログを出力する」というメソッドを作り,呼び出してみましょう。
using UnityEngine; // Action のため using System; public class NewBehaviourScript : MonoBehaviour { void Start() { // Start → A → End の順にログ出力 StartEndChecker(((object o) => Debug.Log(o)), "A"); } /// <summary> /// 任意の処理の前後にログを出力する /// </summary> /// <param name="action">任意の処理</param> /// <param name="obj">任意の処理の引数</param> void StartEndChecker(Action<object> action, object obj) { Debug.Log("Start"); action(obj); Debug.Log("End"); } }
引数に指定したA
という文字が,Start
とEnd
の間に出力されています。
ラムダ式で用意したo
パラメータには,メソッド呼び出し時の第2引数であるA
が割り当てられます。
それでは,o
パラメータを無視してB
という値を直接入力するとどうなるでしょう?
// Start() 内のみ書き換え void Start() { // Start →?→ End の順にログ出力 StartEndChecker(((object o) => Debug.Log("B")), "A"); }
B
と出力されました。
つまり,デリゲート内で直接指定した値の方が優先されるという事です。
これでは第2引数の存在意義がなくなってしまいますし,可読性にも問題があります。
そこで,第2引数を省略する方法を2つ御提案いたします。
既定値付きパラメータ(オプション引数)にする
第2パラメータであるobj
に既定値を設定すると,呼び出し時に省略する事が出来ます。
using UnityEngine; // Action のため using System; public class NewBehaviourScript : MonoBehaviour { void Start() { // Start →?→ End の順にログ出力 StartEndChecker((object o) => Debug.Log("B")); } /// <summary> /// 任意の処理の前後にログを出力する /// </summary> /// <param name="action">任意の処理</param> /// <param name="obj">任意の処理の引数</param> void StartEndChecker(Action<object> action, object obj = default) { Debug.Log("Start"); action(obj); Debug.Log("End"); } }
StartEndChecker()
の呼び出し時に第2パラメータであるobj
を省略すると,default
が代入されます。
そこに直接B
を指定し上書きしているため,先程のA
のような意味のない引数を書く必要がありません。
パラメータ配列(可変長引数)にする
第2パラメータであるobj
をパラメータ配列にすると,呼び出し時に省略する事が出来ます。
using UnityEngine; // Action のため using System; public class NewBehaviourScript : MonoBehaviour { void Start() { // Start →?→ End の順にログ出力 StartEndChecker((object[] objs) => Debug.Log("B")); } /// <summary> /// 任意の処理の前後にログを出力する /// </summary> /// <param name="action">任意の処理</param> /// <param name="objs">任意の処理の引数</param> void StartEndChecker(Action<object[]> action, params object[] objects) { Debug.Log("Start"); action(objects); Debug.Log("End"); } }
StartEndChecker()
の呼び出し時に第2パラメータであるobjects
を省略すると,長さゼロのobject
配列が代入されます。
そこに直接B
を指定し上書きしているため,先程のA
のような意味のない引数を書く必要がありません。
ちなみに,呼び出し時の第2引数を適用したい場合は以下のような記法になります。
// Start() 内のみ書き換え void Start() { // Start → A → End の順にログ出力 StartEndChecker(((object[] objs) => Debug.Log(objs[0])), "A"); }
終わりに
パラメータが複雑に絡み合うため,正確に理解する事が重要ですね。
以上,型パラメータありデリゲートのパラメータ化についてでした。