VB.NET经过长时间的发展,很多用户都很了解VB.NET WithEvents了,这里我发表一下个人理解,和大家讨论讨论。VB除了可以用C#那样的方法来处理事件响应以外,还有从VB5继承下来的独特的事件处理方式——VB.NET WithEvents。
我喜欢称这种事件处理方式为静态的事件处理,书写响应事件的方法时就已经决定该方法响应的是哪一个事件,而C#则是在代码中绑定事件的。比如下面这个最简单的例子:
- Public Class HandlerClass
- Public WithEvents MyObj As EventClass
- Private Sub MyObj_MyEvent(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyObj.MyEvent
- MsgBox("hello")
- End Sub
- Public Sub New()
- MyObj = New EventClass
- End Sub
- End Class
代码中用到的EventClass是这样的:
- Public Class EventClass
- Public Event MyEvent As EventHandler
- Protected Overridable Sub OnMyEvent(ByVal e As EventArgs)
- RaiseEvent MyEvent(Me, e)
- End Sub
- Public Sub Test()
- OnMyEvent(New EventArgs)
- End Sub
- End Class
我们来复习一下,这段代码隐式地给EventClass编写了两个方法——Add_MyEvent(EventHandler)和 Remove_MyEvent(EventHandler),实际上任何使用事件的上下文都是通过调用这两个方法来绑定事件和解除绑定的。C#还允许你书写自己的事件绑定/解除绑定的代码。
那么WithEvents是怎么工作的呢?VB.net的编译器在编译时自动将
- Public WithEvents MyObj As EventClass
翻译成下面这个过程:
- Private _MyObj As EventClass
- Public Property MyObj() As EventClass
- Get
- Return _MyObj
- End Get
- Set(ByVal Value As EventClass)
- If Not (Me._MyObj Is Nothing) Then
- RemoveHandler _MyObj.MyEvent, AddressOf MyObj_MyEvent
- End If
- Me._MyObj = Value
- If Me._MyObj Is Nothing Then Exit Property
- AddHandler _MyObj.MyEvent, AddressOf MyObj_MyEvent
- End Set
- End Property
由此可见,当对VB.NET WithEvents变量赋值的时候,会自动触发这个属性以绑定事件。我们所用的大部分事件响应都是1对1的,即一个过程响应一个事件,所以这种VB.NET WithEvents静态方法是非常有用的,它可以显著增强代码可读性,同时也让VB.net中的事件处理非常方便,不像C#那样离开了窗体设计器就必须手工绑定事件。
不过在分析这段IL的时候,我也发现了VB.net在翻译时小小的问题,就是ldarg.0出现得过多,这是频繁使用Me或this的表现,所以我们在编码过程中一定要注意,除了使用到Me/this本身引用以外,使用它的成员时不要带上Me/this,比如Me.MyInt = 1就改成MyInt = 1,这样的小习惯会为你带来很大的性能收益。
【编辑推荐】