VB.NET下的事件和委托
委托是可用于調(diào)用其他對象方法的對象。它們有時被稱為類型安全函數(shù)指針,因為它們與其他編程語言中所使用的函數(shù)指針相似。但不同于函數(shù)指針,VB.NET 委托是基于 System.Delegate 類的引用類型,它可以引用共享方法—無需特定的類實例即可調(diào)用的方法和實例方法。
委托在調(diào)用過程和被調(diào)用過程需要媒介的情況下是很有用的。例如,您可能想讓一個引發(fā)事件的對象能夠在不同的環(huán)境下調(diào)用不同的事件處理程序。不幸的是,引發(fā)事件的對象無法提前知道處理特定事件的事件處理程序。Visual Basic .NET 通過在使用 AddHandler 語句時創(chuàng)建委托,可讓您動態(tài)地將事件處理程序與事件關(guān)聯(lián)。在運行時,委托將各種調(diào)用轉(zhuǎn)發(fā)到相應(yīng)的事件處理程序。
盡管可以創(chuàng)建自己的委托,但在大多數(shù)情況下,Visual Basic .NET 為您創(chuàng)建委托并提供具體信息。例如,Event 語句將名為 <EventName>EventHandler 的委托類隱式定義為 Event 語句所在類的嵌套類,且其簽字與該事件相同。AddressOf 語句則隱式創(chuàng)建委托的實例。例如,以下兩行代碼是等效的:
- AddHandler Button1.Click
- AddressOf Me.Button1_Click
- ' AddHandler 指向引發(fā)事件的對象,AddressOf則確定該事件對象所要調(diào)用的事件處理程序
- '上述行為又可以稱為 監(jiān)視
- AddHandler Button1.Click, New EventHandler(AddressOf Button1_Click)
只要編譯器可以用上下文確定委托的類型,就可以使用速寫方法創(chuàng)建委托。
注:處理自基類繼承的事件
派生類(繼承某個基類特征的類)能用 Handles MyBase 語句處理它們的基類所引發(fā)的事件。
處理來自基類的事件
通過給事件處理程序過程的聲明行添加 Handles MyBase.<event name> 語句來聲明派生類中的事件處理程序,其中的 event name 是基類中正在處理的事件的名稱。例如:
- Public Class Class1
- Public Event SE(ByVal i As Integer)
- ' Place methods and properties here.
- End Class
- Public Class Class2
- Inherits Class1
- Sub EventHandler(ByVal x As Integer) Handles MyBase.SE
- ' Place code to handle events from Class1 here.
- End Sub
- End Class
聲明使用現(xiàn)有委托類型的事件
某些情況下,可能會要聲明某事件使用現(xiàn)有委托類型為基礎(chǔ)委托。以下語法說明了進行聲明的方式:
Event AnEvent As DelegateType該語法在將多個事件路由到同一處理程序時是很有用的,不過使用現(xiàn)有委托類型時需要先進行如下定義:
- delegate {sub|function} DelegateType(參數(shù)1,參數(shù)2)
下面是vb.net控制臺程序演示單一事件委托多處理程序.
比如說在社會上,你是法律,社會上有三種人,警察、無賴和自愿反扒隊。
你規(guī)定:如果小偷偷東西,則警察處罰小偷500元錢,自愿反扒隊要打無賴進醫(yī)院一次
這就是現(xiàn)實中的委托。
實際上,在寫程序中,程序員就是法律,警察、小偷和自愿反扒隊就是三個對象。小偷偷東西是一個方法,小偷還有一個偷東西事件,他偷東西激發(fā)這個事件。而警察和自愿反扒隊就是兩個事件處理對象,警察負責把小偷的錢扣除500,自愿反扒隊需要大小偷進醫(yī)院一次。
所以,委托有如下幾個要素:
- 激發(fā)事件的對象--就是小偷
- 處理對象事件的對象--就是警察和自愿反扒隊
- 定義委托,就是法律讓警察和自愿反扒隊監(jiān)視小偷。
如果這三個要素都滿足的話,則你就寫出了一個完整事件的處理。
下面是vb.net控制臺的實例
- Imports System
- Module Module1
- '準備引用 無賴 類的偷東西事件
- Public WithEvents w As 無賴
- Sub Main()
- Console.WriteLine("新的一天開始了....")
- ' 實例華警察、無賴、自愿反扒隊 類
- Dim p As New 警察
- w = New 無賴
- Dim pp As New 自愿反扒隊
- '設(shè)置對無賴類的偷東西事件的監(jiān)視,并設(shè)置相應(yīng)的事件處理程序
- '如果小偷玩偷東西則引用警察的罰錢處理程序
- AddHandler w.PlayGame, AddressOf p.扣錢
- '如果小偷偷東西則引用自愿反扒隊的打人處理程序
- AddHandler w.PlayGame, AddressOf pp.打人
- w.偷東西()
- Console.WriteLine("天黑了....")
- Console.ReadLine()
- End Sub
- 'End Class
- Public Class 警察
- Sub New()
- Console.WriteLine("生成警察......")
- End Sub
- '定義的事件處理程序的參數(shù)類型要與定義的委托的參數(shù)類型相一致
- Public Sub 扣錢(ByVal sender As Object, ByVal e As System.EventArgs)
- Console.WriteLine("警察:好小子,膽敢偷東西...")
- '定義線程輸出遲緩3秒
- System.Threading.Thread.Sleep(3000)
- Console.WriteLine("警察:看看你小子有多少錢...")
- Dim f As 無賴 = sender
- System.Threading.Thread.Sleep(3000)
- Console.WriteLine("無賴 的錢: " + f.錢.ToString())
- System.Threading.Thread.Sleep(3000)
- Console.WriteLine("開始扣錢......")
- System.Threading.Thread.Sleep(3000)
- f.錢 = f.錢 - 500
- Console.WriteLine("扣完了....現(xiàn)在無賴 還剩下:" + f.錢.ToString())
- System.Threading.Thread.Sleep(3000)
- End Sub
- End Class
- Public Class 無賴
- '先定義一個偷東西的事件使用現(xiàn)有委托類型 PlayGameHandler為基礎(chǔ)委托
- Public Event PlayGame As PlayGameHandler
- Private m_Money As Integer
- Private ey As Integer
- Sub New()
- Console.WriteLine("生成無賴....")
- m_Money = 1000
- ey = 5
- End Sub
- '定義挨打?qū)傩杂脕碛涗洶ご蜻^幾次
- Property 挨打() As Integer
- Get
- Return ey
- End Get
- Set(ByVal Value As Integer)
- ey = Value
- End Set
- End Property
- '定義前屬性用來記錄有多少錢
- Property 錢() As Integer
- Get
- Return m_Money
- End Get
- Set(ByVal Value As Integer)
- m_Money = Value
- End Set
- End Property
- '定義偷東西過程
- Public Sub 偷東西()
- Console.WriteLine("無賴開始偷東西了")
- System.Threading.Thread.Sleep(3000)
- '實例化事件參數(shù)
- Dim e As New System.EventArgs
- '引發(fā)偷東西事件,參數(shù)類型要與現(xiàn)有委托類型一致
- RaiseEvent PlayGame(Me, e)
- End Sub
- End Class
- Public Class 自愿反扒隊
- Sub New()
- Console.WriteLine("自愿反扒隊來了.....")
- System.Threading.Thread.Sleep(3000)
- End Sub
- '定義的事件處理程序的參數(shù)類型要與定義的委托的參數(shù)類型相一致
- Public Sub 打人(ByVal sender As Object, ByVal e As System.EventArgs)
- System.Threading.Thread.Sleep(3000)
- Console.WriteLine("自愿反扒隊:好小子,敢偷東西...")
- System.Threading.Thread.Sleep(3000)
- Console.WriteLine("自愿反扒隊:你小子挨過幾次打了...")
- Dim bn As 無賴 = sender
- System.Threading.Thread.Sleep(3000)
- Console.WriteLine("無賴:" + bn.挨打.ToString + "次")
- System.Threading.Thread.Sleep(3000)
- Console.WriteLine("自愿反扒隊:那也得揍你,先來一拳.... ")
- System.Threading.Thread.Sleep(3000)
- Console.WriteLine("自愿反扒隊:再來一腳......")
- System.Threading.Thread.Sleep(3000)
- Console.WriteLine("自愿反扒隊:打完了...趕緊去醫(yī)院吧...")
- End Sub
- End Class
- '定義委托類型
- Delegate Sub PlayGameHandler(ByVal sender As Object, ByVal e As System.EventArgs)
- End Module
進一步閱讀:談JavaScript中的事件委托
【編輯推薦】