デリゲート (Visual Basic)

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

デリゲートとイベント

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

独自のデリゲートを作成することもできますが、ほとんどの場合、デリゲートの作成と詳細の管理は 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

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

関連トピック

Title

Description

方法: デリゲート メソッドを呼び出す (Visual Basic)

この例では、メソッドとデリゲートを関連付け、デリゲートによってメソッドを呼び出す方法について説明します。

方法 : Visual Basic でプロシージャを別のプロシージャに渡す

デリゲートを使用してプロシージャを別のプロシージャに渡す方法について説明します。

厳密でないデリゲート変換 (Visual Basic)

シグネチャが一致しない場合でも、Sub や関数をデリゲートやハンドラーに割り当てる方法について説明します。

イベント (Visual Basic)

Visual Basic のイベントの概要について説明します。