詳細(xì)分析VB.NET WithEvents
VB.NET經(jīng)過長(zhǎng)時(shí)間的發(fā)展,很多用戶都很了解VB.NET WithEvents了,這里我發(fā)表一下個(gè)人理解,和大家討論討論。VB除了可以用C#那樣的方法來處理事件響應(yīng)以外,還有從VB5繼承下來的獨(dú)特的事件處理方式——VB.NET WithEvents。
我喜歡稱這種事件處理方式為靜態(tài)的事件處理,書寫響應(yīng)事件的方法時(shí)就已經(jīng)決定該方法響應(yīng)的是哪一個(gè)事件,而C#則是在代碼中綁定事件的。比如下面這個(gè)最簡(jiǎn)單的例子:
- 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
我們來復(fù)習(xí)一下,這段代碼隱式地給EventClass編寫了兩個(gè)方法——Add_MyEvent(EventHandler)和 Remove_MyEvent(EventHandler),實(shí)際上任何使用事件的上下文都是通過調(diào)用這兩個(gè)方法來綁定事件和解除綁定的。C#還允許你書寫自己的事件綁定/解除綁定的代碼。
那么WithEvents是怎么工作的呢?VB.net的編譯器在編譯時(shí)自動(dòng)將
- Public WithEvents MyObj As EventClass
翻譯成下面這個(gè)過程:
- 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
由此可見,當(dāng)對(duì)VB.NET WithEvents變量賦值的時(shí)候,會(huì)自動(dòng)觸發(fā)這個(gè)屬性以綁定事件。我們所用的大部分事件響應(yīng)都是1對(duì)1的,即一個(gè)過程響應(yīng)一個(gè)事件,所以這種VB.NET WithEvents靜態(tài)方法是非常有用的,它可以顯著增強(qiáng)代碼可讀性,同時(shí)也讓VB.net中的事件處理非常方便,不像C#那樣離開了窗體設(shè)計(jì)器就必須手工綁定事件。
不過在分析這段IL的時(shí)候,我也發(fā)現(xiàn)了VB.net在翻譯時(shí)小小的問題,就是ldarg.0出現(xiàn)得過多,這是頻繁使用Me或this的表現(xiàn),所以我們?cè)诰幋a過程中一定要注意,除了使用到Me/this本身引用以外,使用它的成員時(shí)不要帶上Me/this,比如Me.MyInt = 1就改成MyInt = 1,這樣的小習(xí)慣會(huì)為你帶來很大的性能收益。
【編輯推薦】