機能が同じなら一緒に扱え、デリゲートによる関数合成

プログラミングC# 第6版 5.1


デリゲートというものが出てきました。本では長々と説明があったのですが、要するにC++でいうところの関数ポインタってところですね。

否。その認識は間違いです。確かに関数ポインタに似てるんですが、実際はちょっと違います。

デリゲート、僕なりに本を読んで解釈した内容はこうです。

「引数や戻り値の型さえ一致していれば統一的に扱える関数ポインタ」って感じでしょうか。

実際に動作確認してみます。

using System;

// 「戻り値がvoidで引数がintの関数」をデリゲートとして宣言する
delegate void CDelegateClass (int i);

// 「戻り値がvoidで引数がintの関数」を二つほど定義する
static class Hoge {
    public static void Foo (int i) {
        Console.WriteLine("Hoge.Foo: " + i);
    }
    public static void Bar (int i) {
        Console.WriteLine("Hoge.Bar: " + i);
    }
}

class Program {
    // ここでも「戻り値がvoidで引数がintの関数」を定義してみる
    public static void Baz (int i) {
        Console.WriteLine("Baz: " + i);
    }
    
    static void Main () {
        // 「戻り値がvoidで引数がintの関数」を登録する
        // この部分がC++の関数ポインタに見た目が似てますね
        CDelegateClass[] list = {
            new CDelegateClass(Hoge.Foo),
            new CDelegateClass(Hoge.Bar),
            new CDelegateClass(Baz),
        };
        
        foreach(CDelegateClass item in list) {
            // 登録した関数を実行する
            item.Invoke(10);
        }
    }
}
$ main
Hoge.Foo: 10
Hoge.Bar: 10
Baz: 10

それぞれで定義した関数がちゃんと呼ばれていますね。素晴らしいです。

ちなみに関数を登録するところと、関数を呼び出すところはシンタックスシュガーがあります。

    static void Main () {
        // new CDelegateClassを省略できる
        CDelegateClass[] list = {
            Hoge.Foo,
            Hoge.Bar,
            Baz,
        };
        
        foreach(CDelegateClass item in list) {
            // Invokeを省略できる
            item(10);
        }
    }

普段はこの省略形で扱えば良さそうですね。