佐々木屋

技術的なことから趣味まで色々書きます

デリゲート(基本)

デリゲートを本やサイトを調べると、「委譲」であったり、「代表者」、はたまた「C言語の関数ポインタ」という難しい表現が出てきます。ちょっと分かりにくいですよね。そして大抵、読み進めると何が書いてあるか分からなくなるのがデリゲートです。

実はデリゲートを完全に理解するには、デリゲート以外の要素の理解度が大きくかかわってきます。例えばコールバックとか、ラムダ式とか匿名メソッドとかマルチキャストとか。これらが初学者にとって少しハードルを高くしている原因だと私は思います。

デリゲート自体の仕組みは非常に単純なので、今回はそこに絞って少し砕いて説明してみたいと思います。

デリゲートって何なのさ?

簡単に言えば「型」です。stringやintなどと同じ「型」です。ただ、中に入るものはメソッド(への参照情報)が入ります。変数同様、メソッドを入れて保持、実行することが出来ます。

条件があります

デリゲートを作るには条件が2つあり、どちらも満たさなければなりません。
・引数はデリゲートするメソッドの引数(数、型両方)と同一でなければならない
・戻り値はデリゲートするメソッドの戻り値と同一でなければならない


実際につかってみよう

以下のようなクラスのメソッドをデリゲートしてみます。

public class Test1 {
    public void Hoge(string naiyo) {
        Console.WriteLine(naiyo);
    }
}
public class Test2 {
    public void Piyo(string naiyo) {
        Console.WriteLine(naiyo+ naiyo);
    }
}
Public Class Test1
    Public Sub Hoge(ByVal naiyo As String)
        Console.WriteLine(naiyo)
    End Sub
End Class
Public Class Test2
    Public Sub Piyo(ByVal naiyo As String)
        Console.WriteLine(naiyo + naiyo)
    End Sub
End Class

Test1クラスもTest2クラスもどちらにもvoid(Subプロシージャ)で引数string型一つのメソッドがあります。デリゲートする条件である同一引数、同一戻り値(今回は無し)は満たされていますので、どちらのメソッドも一つのデリゲートにすることができます。

//デリゲートの宣言
delegate void ShowDelegate (string value);

//ShowDelegate デリゲートの作成と実行
ShowDelegate dlgate = new Test1().Hoge;
dlgate("fuga");

dlgate = new Test2().Piyo;
dlgate("fuga");
'デリゲートの宣言
Delegate Sub ShowDelegate (ByVal value As String)

'ShowDelegate デリゲートの作成と実行
Dim dlgate As ShowDelegate = AddressOf New Test1().Hoge
dlgate("fuga")

dlgate = AddressOf New Test2().Piyo
dlgate("fuga")
fugafuga
fuga

最初にdelegateキーワードで宣言するのはC#VB.NETも一緒です。

次にnewキーワードを使ってメソッドの参照先のインスタンスを作ってそれを渡すわけですが、C#は感覚的にそのまま書けるのに対し、VB.NETはAddressOf演算子で指定する必要があります(正直この面倒臭さがVB.NETに嫌悪感を抱く人が多い原因でないかと思います)。

メソッドの参照先を渡すと、dlgate は対象となるクラスのメソッドとしての振る舞いを実行できます。よって、最初のdlgate("fuga")はTest1クラスのHogeメソッドが実行され、2番目のdlgate("fuga")はTest2クラスのPiyoメソッドが呼び出されます。