我专门询问 VB.NET,但我想其他语言的一般原则是相同的。我认为事件是 .NET 中的一流概念,但从反思看来,它只是引发事件时调用的特定方法。
- 如何动态修改方法(AFAIK
AddHandler
,事件早于日期?RemoveHandler
DynamicMethod
- 怎么
RaiseEvent
调用方法? - 为什么将
AddHandler
、、RemoveHandler
和RaiseEvent
实现为语句而不是方法?
我专门询问 VB.NET,但我想其他语言的一般原则是相同的。我认为事件是 .NET 中的一流概念,但从反思看来,它只是引发事件时调用的特定方法。
AddHandler
,事件早于日期?RemoveHandler
DynamicMethod
RaiseEvent
调用方法?AddHandler
、、RemoveHandler
和RaiseEvent
实现为语句而不是方法?不,事件只是两个或三个方法的组合(“raise”部分是可选的),就像属性是一个或两个方法的组合一样。
AddHandler
并且RemoveHandler
根本不要修改方法。他们只是调用事件的“添加”和“删除”部分,这对实现部分负责。
通常,事件是通过对具有适当委托类型的字段的引用来实现的,Delegate.Combine
并Delegate.Remove
用于执行适当的操作。(字段值将被更改 - 请记住委托类型是不可变的。)引发事件仅包括调用委托。
至于为什么AddHandler
etc 是单独的语句类型 - 如果它们是方法,参数是什么?有些东西必须提到“事件”。基本上,一个AddHandler
语句对应于适当的事件“add”方法,就像一个属性获取对应于适当的属性“get”方法一样。你可以通过反射来做到这一点,通过EventInfo.AddHandler
。
请参阅我关于委托和事件的文章以获取更多可能有帮助的详细信息 - 它来自 C# 背景,但原则显然是相同的。
一个事件只是一个代表。这里有一些代码可以像常规事件一样使用,而是使用委托对象:
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 混淆。就像更换它或将其设置回无。这在大多数情况下都是灾难性的,首先订阅事件的代码将停止正常工作。
VB.NET 中的Event关键字可以防止这种情况发生。它包装了委托对象,使其无法被其他代码访问,超出了提供的关键字。有点类似于属性如何保护对字段的访问。AddHandler 和 RemoveHandler 确保现有注册不会消失。RaiseEvent 触发事件而不需要Nothing检查。