やってみる

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

C#ツアー デリゲート

 メソッドの参照。型安全な関数ポインタ。

成果物

情報源

デリゲート型の定義と宣言

class Program {
    delegate int GetValue();
    static void Main() {
        GetValue getValue;
        getValue = Get100;
    }
    static int Get100() => 100;
}

 インスタンスメソッドに対しても使える。

class Main {
    delegate int GetValue();
    public void Run()
    {
        GetValue getValue;
        getValue = Get100;
    }
    int Get100() => 100;
}

マルチキャストデリゲート

 複数のメソッドをセットできる。呼び出せばすべてのメソッドが実行される。

class Main
{
    delegate int GetValue();
    public void Run()
    {
        GetValue getValue;
        getValue  = Get100;
        getValue += Get0_99;
        Console.WriteLine($"{getValue()}");
    }
    int Get100() { Console.WriteLine("called Get100."); return 100; }
    int Get0_99() { Console.WriteLine("called Get0_99."); return new Random().Next(100); }
}

 ただし、戻り値は最後のGet0_99メソッドの値だけだった。

エラー

デリゲートの型宣言を関数内でやるとエラー

error CS1514: { expected
error CS1002: ; expected

 クラスのメンバ変数として宣言してやると成功する。

class Main {
    public void Run() {
        delegate int GetValue(); // error
        GetValue getValue;
        getValue = Get100;
    }
    int Get100() => 100;
}

 おそらくdelegateは型の一種。型の定義はメソッド内では不可。namespaceclass内で定義するものなのだろう。たぶん。

用途

述語

class Main
{
    delegate bool Predicate(int i);
    public void Run()
    {
        Predicate p;
        int[] a = {1,2,3,4,5};
        p = IsEven;
        int[] evens = Select(a, p);
        Show(evens);
        p = IsOdd;
        int[] odds = Select(a, p);
        Show(odds);
    }
    int[] Select(int[] a, Predicate p) 
    {
        List<int> list = new List<int>();
        foreach (int v in a) {
            if (p(v)) { list.Add(v); }
        }
        return list.ToArray();
    }
    bool IsEven(int i) => (0 == (i % 2));
    bool IsOdd(int i) => (1 == (i % 2));
    void Show(int[] a) { foreach (int i in a) { Console.WriteLine($"{i}"); } }
}

 Selectは、配列aの要素が述語pである要素のみの配列を返す。

 述語は変数にできる。この場合は以下2通り。

  • IsEven: 偶数である
  • IsOdd: 奇数である

 好きな述語メソッドを定義できる。使うときは自由に選択できる。

対象環境

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