Visual Basic (VB.NET) では、デリゲートは特定のシグネチャを持つメソッドへの参照を含む型であり、イベント処理の基礎を成します。イベントはデリゲートに基づいて構築されており、オブジェクトが他のオブジェクトに発生した変更を通知できるようにします。
標準イベントには、例えば EventHandler のような既定のデリゲートが使用されますが、ユーザー定義イベントには必要なシグネチャを持つ独自のデリゲートを定義できます:
'ユーザー定義デリゲートとイベントの宣言 Public Delegate Sub ChangedEventHandler(sender As Object, e As EventArgs) Public Event Changed As ChangedEventHandler 'イベントの使用 Public Sub OnChanged() RaiseEvent Changed(Me, EventArgs.Empty) End Sub
細かい点:
なぜVisual Basicでイベントをクラスの外から呼び出すことができないのか、Publicとして宣言されている場合でも?
答え: アクセス修飾子Publicにもかかわらず、イベントはクラスの外部から「サブスクライブ」または「サブスクライブ解除」することはできますが、呼び出し(RaiseEvent)はクラス内でのみ可能です — これは、カプセル化とイベント配信の制御を確保するための言語の特性です。例えば:
Public Class Foo Public Event MyEvent() End Class Dim f As New Foo() ' これはできません: f.RaiseEvent MyEvent() — コンパイラはこれを許可しません。
物語
Windows Formsプロジェクト: 開発者は、データクラスの外部から「DataUpdated」イベントを呼び出そうとしましたが、失敗しました。イベントは処理されず、イベントのスコープに関する誤解からアーキテクチャをリファクタリングし、ロジックを変更しなければなりませんでした。
物語
Webサービス: デリゲートを宣言する際に、シグネチャの一部の変数を省略しました。イベントはサブスクライブされましたが、実行時エラーで呼び出されました - サブスクライバーは1つの引数を期待していましたが、呼び出しは2つで行われました。
物語
1Cプラグイン: 開発者はFieldInfo.SetValueを使用してRaiseEventの呼び出しを模擬しました。これにより、インターフェイスの状態の不一致と、アセンブリの更新時にクラッシュが発生しました。