2

以下のコードを見てください。これは期待どおりに機能します。

Partial Class _Default
    Inherits System.Web.UI.Page


    Delegate Sub TestEventHandler(ByVal o As Object, ByVal e As EventArgs)
    Dim alhandler As TestEventHandler = AddressOf TestEventMethod
    Public Event Test1 As TestEventHandler
    Public Event Test2 As TestEventHandler

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        AddHandler Me.Test1, alhandler
        AddHandler Me.Test2, alhandler
        RaiseEvent Test1(Me, e)
        RaiseEvent Test2(Me, e)
        RemoveHandler Me.Test1, alhandler
        RaiseEvent Test1(Me, e)
    End Sub

    Public Sub TestEventMethod(ByVal o As Object, ByVal e As EventArgs)
        MsgBox("Test")
    End Sub


End Class

以下の2つのステートメントと混同しています。

Dim alhandler As TestEventHandler = AddressOf TestEventMethod '1
Public Event Test1 As TestEventHandler '2

1) これは、alHandler の参照が、関数のアドレスを指すデリゲートであることを示しています。2) これは、Test1 がデリゲート タイプのイベントであることを示しています。イベントとハンドラをどのようにデリゲートにすることができますか?

4

1 に答える 1

4

他の人が言ったように、デリゲートの各タイプは、通常のクラスと同じようにタイプです。したがって、コード例でTestEventHandlerは、デリゲート型です。TestEventHandler変数は、他のTestEventHandler変数がそれ自体の型の任意のオブジェクトを参照できるのと同様に、任意のオブジェクトを参照できます。 TestEventHandlerオブジェクトは、他のタイプのオブジェクトと同様にインスタンス化する必要があります。

ただし、デリゲートは、別の特別な構文を使用して宣言するという点で特別です。たとえば、次のメソッドがあるとします。

Public Sub MyMethod(Text As String)
    ' ...
End Sub

次のように、そのメソッド シグネチャに一致するデリゲートを作成できます。

Public Delegate Sub MyMethodDelegate(Text As String)

そうすることで、単純に型を定義することを忘れないでくださいMyMethodDelegate。その型の変数を宣言することも、その型のオブジェクトをインスタンス化することもありません。

ただし、VB.NET の構文には 2 つの点があり、しばしば混乱を招きます。まず、イベントを宣言するとき、次の 2 つの異なる構文を使用できます。

Public Event MyEvent As MyMethodDelegate
Public Event MyEvent(Text As String)

これらの行はどちらも同じことを行います。最初の行では、定義済みのデリゲート型を使用してイベントを定義しています。2 行目は基本的に、名前のない新しいデリゲートをオンザフライで定義し、それをイベントの型として使用します。 (簡単にするために を使用していることに注意してください。これはMyMethodDelegate機能しますが、標準では、イベントには送信者とイベント引数が必要であると規定されています。) イベントが宣言されたら、それを変数のように考えてください。舞台裏では、AddHandler関数を使用して追加されたすべてのデリゲート オブジェクトのリストを保持するコレクション オブジェクトのようなものです。

VB.NET の 2 つ目の紛らわしい点は、関数を使用するときに、必要に応じてコンパイラが新しいデリゲート オブジェクトを自動的にインスタンス化することですAddressOf。たとえば、次のようなことをするとします。

AddHandler myObject.MyEvent, AddressOf MyMethod

次のように、全文を入力するための単なるショートカットです。

AddHandler myObject.MyEvent, New MyMethodDelegate(AddressOf MyMethod)

私の意見では、後者の方がはるかに明確です。実際に行っているのは、そのデリゲート型の新しいオブジェクトを作成し、そのデリゲート オブジェクトをそのメソッドにポイントしてから、そのデリゲート オブジェクトをイベント (オブジェクトの型によって定義されたイベント コレクションのような変数) に追加することです。

したがって、あなたの例では、この行:

Dim alhandler As TestEventHandler = AddressOf TestEventMethod

より明確に次のように記述します。

Dim alhandler As TestEventHandler = New TestEventHandler(AddressOf TestEventMethod)

デリゲート変数を宣言し、その特定のメソッドを指す新しいデリゲート オブジェクトに設定します。この場合、これは単なる標準デリゲート変数であり、イベントではありません。イベントはデリゲートのフィールド/プロパティに非常に似ています。プロパティがプライベート フィールドをラップすることが多いのと同じように、イベントは本質的にプライベート デリゲート フィールドのアクセサー ラッパーです。デリゲート フィールドとイベントの大きな違いは、イベントがAddHandlerandEventHandler関数をサポートし、イベントを定義するクラスの外部からイベントを発生させたり呼び出したりできないことです。

于 2013-02-25T19:30:27.787 に答える