ロバメモ - 素人のUnity覚書と奮闘記

素人のUnity覚書と奮闘記

デリゲート,コールバック,ラムダ式,非同期とやらを調べてみた①Delegate

前々から、ちょくちょくお見かけするなぁとは思っていたけど、スルーするのも限界が来たので、ちょっと調べてみた。
私は理系でもなければ学もない、感覚的にプログラムを理解しようとするタイプ(笑)なので、ちゃんと知りたい人には、この記事は向かないです。

Delegate(デリゲート)とは

平たく言えば、”メソッドを参照するための型”らしい。
と言われても、ピンと来ない。そもそも、メソッドなら直接呼び出せばいいのに、なんのために型が必要なのか?というか、ぶっちゃけ”型”とか言われても・・・困惑w
そんな疑問や不安を抱きつつ、それがどういうことなのかをコードから紐解いてみる。

基本的なデリゲートの形

例として、コンソールに"Hello"と表示する関数:Methodをdelegate:Dele型から参照して実行するコードを挙げる。

public class Example : MonoBehaviour{
    //参照したいメソッド
    void Method()
    {
        Debug.Log("Hello");
    }

    //型を定義
    delegate void Dele();

    void Start()
    {
        //インスタンス生成
        Dele dele = new Dele(Method);

        //実行
        dele();
    }
}

出力結果

Hello

定義

まずは宣言している場所に注目。
変数ならば、Start()内でローカル変数として扱えそうなものだけど、そうするとエラーになる。
delegateはフィールドで宣言しないといけないみたい。ちなみに、下記の方法でもいいらしい。

//ここ(クラスの外側)に書いてもOK
delegate void Dele();

public class Example : MonoBehaviour{...}

書式は下記の通り
f:id:nico-taniku:20201231132347p:plain
名前の後ろに()が付いてる感じがメソッドっぽい書き方よね。
いつも通り、呪文のように暗記すればいいかと思った人、ちょっと待った!
どうやらこういう書き方でデリゲートを使うことはほとんどないらしい。
というのも、後述するが、ActionやFuncを使うとデリゲートで書く定義を簡略化できるため、書く必要がないみたい。

インスタンス生成

なんか、もう、インスタンスとか文字を目にしただけでオブジェクト指向アレルギーが発症しそう。
まぁ、定義しただけでは使えない(実体がないとかいうやつ)ので、インスタンスとやらを作りましょう。

//型の名前 インスタンス名 = new 型の名前(参照したいメソッド)
Dele dele = new Dele(Method);

//new使わなくてもOKみたい
Dele dele = Method;

宣言で付けた名前が型になってるぜ!?って混乱した人〜(笑)
Deleって型の名前だからこれでいいのだ。
メソッドを代入してるので、”メソッドを参照するための型”というのが分かった気がする。

実行

//インスタンス名();
dele();

参照しているメソッドを実行するんだから()が付くのもなんかわかる気がする。
しかし、メソッドに引数や戻り値がある場合はどうなるの?という疑問が出てくる。

引数がある場合

参照したいメソッドに引数がある場合。

//デリゲートに渡すメソッド
void Method(string str)
{
    Debug.Log(str);
}

//デリゲートの定義
delegate void Dele(string s);

void Start(){
    //生成
    Dele dele = new Dele(Method);

    //実行
    dele("Hello");
}

概ね前項と同じ書き方になる。
ポイントは定義する時にメソッドの引数と同じ型の引数を用意すること。

戻り値がある場合

参照したいメソッドに戻り値がある場合。

//デリゲートに渡すメソッド
string Method()
{
    return "Hello";
}

//デリゲートの定義
delegate string Dele();

void Start(){
    //生成
    Dele dele = new Dele(Method);

    //実行 出力結果:Hello
    var str = dele();
    Debug.Log(str);
}

デリゲートを定義するときに戻り値を参照したいメソッドと同じ型にしておく。

以上。

次の記事:デリゲート,コールバック,ラムダ式,非同期とやらを調べてみた②ActionとFuncについて - ロバメモ - 素人のUnity覚書と奮闘記

関連記事

Delegate
ActionとFunc
コールバック
ラムダ式
非同期