デリゲートとは?

デリゲートとは、「C言語の関数ポインタのようなもです」と解説されているのを見かけます。

では、関数ポインタとは何でしょう?プログラムは、変数や関数といった物のかたまりですが 変数がメモリ上のどこかに配置されるように、関数もどこかに配置されます。 配置される場所には、アドレスを持っているためそのアドレスを参照することで関数へ たどり着くことができます。このアドレスを格納するポインタを「関数ポインタ」といいます。

VB2005でのデリゲートの宣言は、次のように記述します。

Delegate Sub デリゲートの名前 (引数リスト)
Delegate Function デリゲートの名前 (引数リスト) As 戻り値のデータ型

実際に使ってみる

まず、デリゲートを宣言します。次の例では、ログを吐き出す関数を対象にしています。 デリゲートの宣言では、引数に文字列を受取る関数を宣言しています。

Delegate Sub log(ByVal msg As String)

Sub TraceLog(ByVal LogMsg As String)
    Trace.WriteLine(LogMsg)
End Sub

Private Sub hoge_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
                        Handles MyBase.Load

    Dim logWriter As New log(AddressOf TraceLog)

    logWriter.Invoke("AppStart")
End Sub

ロードイベントでlogデリゲートクラスのインスタンス化と関数を関係付けます。

Invokeにより実際の関数が実行されます。(Invokeは、既定メンバのため省略可能です。)

関数を差し替えてみる

次にイベントログにメッセージを吐き出す関数を用意します。引数は、TraceLogと同様に メッセージを受取ります。

AddressOf 以降の対象を変更することでログの出力先をイベントログに変更することができます。

Delegate Sub log(ByVal msg As String)

Sub TraceLog(ByVal LogMsg As String)
    Trace.WriteLine(LogMsg)
End Sub

Private Sub hoge_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
                        Handles MyBase.Load

    Dim logWriter As New log(AddressOf EventLog)

    logWriter.Invoke("AppStart")
End Sub

Sub EventLog(ByVal LogMsg As String)
    If Not System.Diagnostics.EventLog.SourceExists("hoge") Then
        System.Diagnostics.EventLog.CreateEventSource("hoge", "Application")
    End If
    Dim eventLog As New System.Diagnostics.EventLog()

    eventLog.Source = "hoge"
    eventLog.WriteEntry(LogMsg)
End Sub

デリゲートの基底クラスは

デリゲートは、System.MulticastDelegateから派生しておりこのSystem.MulticastDelegateは、System.Delegate から派生しています。

基底クラスのコンストラクタでは、引数を2つ取るようになっていますが(targetとmethod)実装する際は、 AddressOfで指定している1つだけを渡しています。