如何实施事件

时间:2013-04-29 14:27:26

标签: .net events implementation

我是专门询问VB.NET,但我想其他语言的一般原则是相同的。我认为一个事件是.NET中的一流概念,但似乎reflection它只是一个特定方法,它在事件被引发时被调用。

  1. AddHandlerRemoveHandler如何动态修改方法(AFAIK,事件为DynamicMethod之前的事件?
  2. RaiseEvent如何调用该方法?
  3. 为什么AddHandlerRemoveHandlerRaiseEvent实现为语句而不是方法

2 个答案:

答案 0 :(得分:2)

不,事件只是两个或三个方法的组合(“提升”部分是可选的),就像属性是一个或两个方法的组合一样。

AddHandlerRemoveHandler根本不会修改方法。他们只是调用事件的“添加”和“删除”部分,这些部分可用于实现部分。

通常,事件是通过引用具有适当委托类型的字段来实现的,Delegate.CombineDelegate.Remove用于执行适当的操作。 (字段值将被更改 - 请记住委托类型是不可变的。)引发事件只需要调用委托。

至于为什么AddHandler等是单独的语句类型 - 如果它们是方法,那么参数是什么?有些事情必须提到“事件”。基本上,AddHandler语句对应于适当的事件“add”方法,就像属性提取对应于适当的属性“get”方法一样。您可以 通过EventInfo.AddHandler进行反思。

请参阅我的article on delegates and events以获取更多可能有用的详细信息 - 它来自C#背景,但原则显然是相同的。

答案 1 :(得分:1)

事件只是一个代表。这里有一些代码可以像常规事件一样使用委托对象代替:

Module Module1
    Sub Main()
        Dim obj As New Example
        obj.AnEvent = New EventHandler(AddressOf Handler)
        obj.Test()
        Console.ReadLine()
    End Sub

    Sub Handler(ByVal sender As Object, ByVal e As EventArgs)
        Console.WriteLine("got event")
    End Sub
End Module

Class Example
    Public AnEvent As EventHandler
    Public Sub Test()
        If AnEvent IsNot Nothing Then AnEvent(Me, EventArgs.Empty)
    End Sub
End Class

但请注意此代码的问题。其他一些代码也可能与AnEvent混乱。喜欢替换它或将其设置为Nothing。这在任何情况下都是灾难性的,首先订阅事件的代码将停止正常工作。

VB.NET中的 Event 关键字可以防止这种情况发生。它包装委托对象,并使其他代码无法访问,超出了提供的关键字。与Property如何保护对字段的访问有些类似。 AddHandler和RemoveHandler确保现有注册不会消失。 RaiseEvent在不需要 Nothing 检查的情况下触发事件。