やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

C#の概念 デリゲート

 delegate, Action, Func

成果物

情報源

デリゲート

 関数ポインタのこと。変数の関数版みたいなもの。任意の関数をセットして呼び出せる。

 デリゲートにも型がある。関数における引数・戻り値の数や型が一致していれば、同一型と判断される。

コード

delegate

 引数や戻り値がないデリゲート型を定義する。次にその型における変数を宣言する。

class Main {
    delegate void ShowDelegate(); // 型
    ShowDelegate ShowAction { get; set; } // 変数
}

 デリゲート変数にセットする関数を用意する。

private void HelloShow() => Console.WriteLine("Hello world !!");

 デリゲート変数に関数をセットする。デリゲート変数を呼び出す。

public void Run() {
    ShowAction = HelloShow;
    ShowAction();
}

 実行結果は以下。

Hello world !!

引数や戻り値があるときの例

class Main {
    delegate int GetIntDelegate(int i);
    GetIntDelegate GetIntFunc { get; set; }
    int GetInt(int i) { return 100; }
    public void Run() {
        GetIntFunc = GetInt;
        Console.WriteLine($"{GetIntFunc(1)}");
    }
}

既存のデリゲート型

デリゲート型 引数 戻り値
Action なし なし
Action<引数型,...> あり なし
Func<戻り値型> なし あり
Func<引数型,...,戻り値型> あり あり

 これに一致すればデリゲート型を作らずに済む。

Action

class Main {
    private Action ShowAction { get; set; }
    private Action<string> ShowMessageAction { get; set; }

    public void Run() {
        ShowAction = HelloShow;
        ShowMessageAction = HelloShowMessage;
        ShowAction();
        ShowMessageAction("Lesson 2.");
    }
    private void HelloShow() => Console.WriteLine("Hello world !!");
    private void HelloShowMessage(string message) => Console.WriteLine($"Hello world !! {message}");
}
Hello world !!
Hello world !! Lesson 2.

Function

class Main {
    private Func<string> GetFunc { get; set; }
    private Func<int, string> GetMessageFunc { get; set; }

    public void Run() {
        GetFunc = Get;
        GetMessageFunc = GetMessage;
        Console.WriteLine($"{GetFunc()}");
        Console.WriteLine($"{GetMessageFunc(100)}");
    }
    private string Get() => "Hello world !! Lesson 3.";
    private string GetMessage(int value) => $"value is {value}.";
}
Hello world !! Lesson 3.
value is 100.

所感

 ふつうはデリゲート変数を公開する。外部から自由にメソッドを設定させることで、それを呼び出せるようにする。そうでなければ意味がない。今回は短縮するためprivateにしたが、ふつうはpublicにする。

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux