デリゲート (Visual Basic)

デリゲートは、メソッドを参照するオブジェクトです。 デリゲートは他のプログラミング言語で使用される関数ポインターに似ているため、"タイプ セーフ関数ポインター" と説明されることがあります。 しかしながら、関数ポインターとは異なり、Visual Basic のデリゲートは、System.Delegate クラスに基づく参照型です。 デリゲートは、共有メソッド (特定のクラスのインスタンスがなくても呼び出すことのできるメソッド) とインスタンス メソッドの両方を参照できます。

デリゲートとイベント

デリゲートは、呼び出し側プロシージャと呼び出されるプロシージャの間の媒介手段が必要な状況で役立ちます。 たとえば、イベントを発生させるオブジェクトが、異なる状況で別個のイベント ハンドラーを呼び出せるようにする必要がある場合があります。 しかし、イベントを発生させるオブジェクトは、どのイベント ハンドラーが特定のイベントを処理するかをあらかじめ把握できません。 Visual Basic で AddHandler ステートメントを使用すると、デリゲートを作成して、イベント ハンドラーをイベントに動的に関連付けることができます。 実行時に、デリゲートによって適切なイベント ハンドラーに呼び出しが転送されます。

独自のデリゲートを作成することもできますが、ほとんどの場合、デリゲートの作成と詳細の管理は Visual Basic によって自動的に行われます。 たとえば、Event ステートメントは、Event ステートメントを含むクラスの入れ子のクラスとして、<EventName>EventHandler という名前のデリゲート クラスをイベントと同じシグネチャを使用して暗黙的に定義します。 AddressOf ステートメントは、特定のプロシージャを参照するデリゲートのインスタンスを暗黙的に作成します。 次の 2 つのコード行は同等です。 最初の行では、EventHandler のインスタンスが明示的に作成され、メソッド Button1_Click への参照が引数として渡されます。 2 番目の行は、より便利な方法で同じことを実行します。

AddHandler Button1.Click, New EventHandler(AddressOf Button1_Click)
' The following line of code is shorthand for the previous line.
AddHandler Button1.Click, AddressOf Me.Button1_Click

コンパイラがデリゲートの種類をコンテキストから判断できる場合は、デリゲートの簡単な作成方法を使用できます。

既存の種類のデリゲートを使用するイベントの宣言

状況によっては、基になるデリゲートとして既存のデリゲートを使用するイベントを宣言する必要が生じることがあります。 その方法を次の構文に示します。

Delegate Sub DelegateType()
Event AnEvent As DelegateType

これは、同じハンドラーに複数のイベントをルーティングする場合に役立ちます。

デリゲート変数とパラメーター

デリゲートは、フリースレッド処理や、実行時に異なるバージョンの関数を呼び出す必要があるプロシージャなど、イベントに関連しない他のタスクにも使用できます。

たとえば、自動車の名前のリスト ボックスを含む、項目別広告のアプリケーションがあるとします。 広告はタイトル(通常は自動車の型式) で並べ替えられます。 問題が発生する可能性があるのは、型式の前に年式が含まれている自動車があるときです。 問題になるのは、リスト ボックスに組み込まれた並べ替え機能の並べ替えの基準が文字コードだけであることです。このため、日付で始まるすべての広告が最初に配置され、その後に型式で始まる広告が配置されます。

この問題を解決するために、クラスに並べ替えプロシージャを作成できます。このプロシージャは、ほとんどのリスト ボックスに対応する標準的なアルファベット順の並べ替えを使用しますが、実行時に自動車広告用のカスタム並べ替えプロシージャに切り替えることができます。 このプロシージャを作成するには、デリゲートを使用して実行時にカスタム並べ替えプロシージャを並べ替えクラスに渡します。

AddressOf とラムダ式

各デリゲート クラスでは、オブジェクト メソッドの仕様を渡すコンストラクターを定義します。 デリゲート コンス トラクターに渡す引数は、メソッドへの参照、またはラムダ式である必要があります。

メソッドへの参照を指定するには、次の構文を使用します。

AddressOf [expression.]methodName

コンパイル時の expression の型は、シグネチャがデリゲート クラスのシグネチャと同じで、指定された名前のメソッドを持つクラスまたはインターフェイスである必要があります。 methodName は、共有メソッドまたはインスタンス メソッドのいずれかにできます。 クラスの既定メソッドに対してデリゲートを作成する場合も、methodName は省略できません。

ラムダ式を指定するには、次の構文を使用します。

Function ([parm As type, parm2 As type2, ...]) expression

次の例では、デリゲートの参照を指定するために使用される AddressOf 式とラムダ式を示します。

Module Module1

    Sub Main()
        ' Create an instance of InOrderClass and assign values to the properties.
        ' InOrderClass method ShowInOrder displays the numbers in ascending 
        ' or descending order, depending on the comparison method you specify.
        Dim inOrder As New InOrderClass
        inOrder.Num1 = 5
        inOrder.Num2 = 4

        ' Use AddressOf to send a reference to the comparison function you want
        ' to use.
        inOrder.ShowInOrder(AddressOf GreaterThan)
        inOrder.ShowInOrder(AddressOf LessThan)

        ' Use lambda expressions to do the same thing.
        inOrder.ShowInOrder(Function(m, n) m > n)
        inOrder.ShowInOrder(Function(m, n) m < n)
    End Sub

    Function GreaterThan(ByVal num1 As Integer, ByVal num2 As Integer) As Boolean
        Return num1 > num2
    End Function

    Function LessThan(ByVal num1 As Integer, ByVal num2 As Integer) As Boolean
        Return num1 < num2
    End Function

    Class InOrderClass
        ' Define the delegate function for the comparisons.
        Delegate Function CompareNumbers(ByVal num1 As Integer, ByVal num2 As Integer) As Boolean
        ' Display properties in ascending or descending order.
        Sub ShowInOrder(ByVal compare As CompareNumbers)
            If compare(_num1, _num2) Then
                Console.WriteLine(_num1 & "  " & _num2)
            Else
                Console.WriteLine(_num2 & "  " & _num1)
            End If
        End Sub

        Private _num1 As Integer
        Property Num1() As Integer
            Get
                Return _num1
            End Get
            Set(ByVal value As Integer)
                _num1 = value
            End Set
        End Property

        Private _num2 As Integer
        Property Num2() As Integer
            Get
                Return _num2
            End Get
            Set(ByVal value As Integer)
                _num2 = value
            End Set
        End Property
    End Class
End Module

関数のシグネチャは、デリゲート型のシグネチャと一致している必要があります。 ラムダ式について詳しくは、「ラムダ式」をご覧ください。 ラムダ式のその他の例と AddressOf のデリゲートへの代入については、「厳密でないデリゲート変換」を参照してください。

Title 説明
方法: デリゲート メソッドを呼び出す メソッドをデリゲートに関連付け、デリゲートからそのメソッドを呼び出す方法の例を示します。
方法: Visual Basic でプロシージャを別のプロシージャに渡す デリゲートを使用してプロシージャを別のプロシージャに渡す方法を示します。
厳密でないデリゲート変換 シグネチャが同じでない場合でも Sub や関数をデリゲートやハンドラーに割り当てる方法を説明します。
イベント Visual Basic のデリゲートの概要について説明します。