在 .NET Framework 中引发自定义事件的不同方法

Different ways of raising a Custom Event in .NET Framework

我知道在 VB .Net 中可以定义您的自定义事件处理程序。

这是一种让 class 知道另一个人何时正在侦听其事件的方法。此示例代码来自 MSDN :

Private Events As EventHandlerList

Public Custom Event MyEvent As EventHandler
    AddHandler(value As EventHandler)
        Events.AddHandler("Test", value)
    End AddHandler

    RemoveHandler(value As EventHandler)
        Events.RemoveHandler("Test", value)
    End RemoveHandler

    RaiseEvent(sender As Object, e As EventArgs)
        CType(Events("Test"), EventHandler).Invoke(sender, e)
    End RaiseEvent
End Event

现在,您可以通过以下方式引发自定义事件:

Private Sub MySub()
    RaiseEvent MyEvent(Me, EventArgs.Empty)
End Sub

到目前为止一切顺利,完全没有问题。

我的问题是,因为在我的 class 中我可以直接访问 EventHandlerList,我可以在自定义事件处理程序之外调用它吗? 如果我这样做了,这个潜艇和上面那个潜艇的作用有什么不同吗?

Private Sub MySub2()
    CType(Events("Test"), EventHandler).Invoke(Me, EventArgs.Empty)
End Sub

我知道这可能根本不是好习惯,我只是好奇,因为我可能有一个函数将事件名称作为 String 传递,这样引发事件的方式可能对我有用,我会做类似的事情:

Private Sub RaiseCustomEvent(EventName As String, Ev as EventArgs)
    CType(Events(EventName), EventHandler).Invoke(Me, Ev)
End Sub

My question is, since in my class I have a direct access to the EventHandlerList, can I call it outside the custom event handler?

是的。

And if I do, is there any difference between what this sub does from the one above?

没有。 RaiseEvent 语句只是调用事件声明的 RaiseEvent 部分。 VB.NET 规范说:

The RaiseEvent declaration takes the same parameters as the event delegate and will be called when a RaiseEvent statement is executed.

但请注意,MSDN 示例已损坏---如果未附加事件处理程序 (Fiddle),它会引发 NullReferenceException

Public Module Module1
    Public Sub Main()
        Dim x As New T()
        x.RaiseTestEvent()
    End Sub
End Module

Public Class T
    Private Events As New System.ComponentModel.EventHandlerList()

    Public Custom Event MyEvent As EventHandler
        AddHandler(value As EventHandler)
            Events.AddHandler("Test", value)
        End AddHandler

        RemoveHandler(value As EventHandler)
            Events.RemoveHandler("Test", value)
        End RemoveHandler

        RaiseEvent(sender As Object, e As EventArgs)
            CType(Events("Test"), EventHandler).Invoke(sender, e)
        End RaiseEvent
    End Event

    Public Sub RaiseTestEvent()
        ' Throws NullReferenceException if no event handler is attached.
        RaiseEvent MyEvent(Me, EventArgs.Empty)
    End Sub
End Class

对于 "regular" 事件,如果没有附加处理程序 (Fiddle),RaiseEvent 只是一个 NO-OP。 VB 规范说:

The RaiseEvent statement is processed as a call to the Invoke method of the event's delegate, using the supplied parameters, if any. If the delegate’s value is Nothing, no exception is thrown.