|
“委托”機(jī)制的“委托”到底是什么意思呢,《高級漢語大詞典》中是如下解釋的:托付給別的人或機(jī)構(gòu)辦理。要說生活中的意思其實大家都能理解,無非是“當(dāng)某人(機(jī)構(gòu))需要完成一件自己不能或不應(yīng)該完成的事情的時候,此人(機(jī)構(gòu))物色一個合適的且有能力完成此事的人選,然后提供必要的信息,將此事委托給物色到的人(機(jī)構(gòu))來完成?!?br> 軟件的對象方法其實是對現(xiàn)實世界的模擬,你可能會想現(xiàn)實世界里的委托哪有這么多呢?這么重要呢?其實你也許沒有注意到老板把厚厚的一摞資料摔在你的案頭讓你無論如何在×月×日前交活,這不就是一種委托嗎?當(dāng)然也許沒有委托書(和委任狀),但它就是委托。這樣看委托是不是就非常重要了,它甚至是構(gòu)成現(xiàn)實社會的基礎(chǔ)機(jī)制之一。
從這個意義上理解委托機(jī)制的重要性我想應(yīng)該是足夠了。委托機(jī)制是促使事件發(fā)送與事件接受的一種對接策略,對象對周圍信號的反應(yīng)或在一定環(huán)境中所具備的對其它對象的通知行為的響應(yīng)則被描述成所謂的“事件”,這可以類比人對周圍世界反饋產(chǎn)生信號的能力。
委托就是一種定向信號流:指定產(chǎn)生、接受信號者并產(chǎn)生信號反饋的技術(shù)。
我可愛的小女兒才剛剛學(xué)會說話就在飯桌上支使她可憐的“老”爸:爸爸,把我的小勺子拿來。我接到“信號”立即屁顛屁顛地跑到廚房拿到勺子送到女兒的小手上,一個“委托”完成的非常漂亮,而女兒則無須知道我在什么地方、如何拿到勺子,她只管接受到我給她專門買的小勺子就行,否則,她就要仰著小臉“哇哇”大哭了。
先說說事件委托的基礎(chǔ)。
為了說明問題我設(shè)計了一個窗體還有幾個按鈕的示例DelegateDemo1項目,以便可以直觀感受委托的基本用法。
至于委托在.net中的實現(xiàn),編譯器會自動生成一個完整的類定義:一個構(gòu)造器,Invoke,BeginInvoke,以及EndInvoke。
C#中隱式使用Invoke(其顯式調(diào)用會報錯)會讓我們誤解有一個以委托名稱為名稱的函數(shù),其實沒有,它只是隱式使用Invoke方法。而VB.net包括最新的VB.net2005均可以采取兩種方法(顯式或隱式)使用Invoke方法。我比較喜歡顯式使用它,因為這樣比較貼近事物的本質(zhì)。
回到示例,代碼如下:
Public Class Form1Class Form1 Inherits System.Windows.Forms.Form Private Sub Button1_Click()Sub Button1_Click(ByVal sender As System.Object,_ ByVal e As System.EventArgs) Handles Button1.Click,_ Button2.Click, Button4.Click Select Case CType(sender, Button).Name Case "Button1" MessageBox.Show("你點擊了Button1!", "委托提示", MessageBoxButtons.OK) Case "Button2" MessageBox.Show("你點擊了Button2!", "委托提示", MessageBoxButtons.OK) Case "Button3" MessageBox.Show("你點擊了Button3!", "委托提示", MessageBoxButtons.OK) Case "Button4" MessageBox.Show("你點擊了Button4!", "委托提示", MessageBoxButtons.OK) End Select End Sub Private Sub Button2_Click()Sub Button2_Click(ByVal sender As System.Object,_ ByVal e As System.EventArgs) Handles Button2.Click MessageBox.Show("Button2的Click事件,注意執(zhí)行順序!", "委托提示", MessageBoxButtons.OK) End Sub Private Sub Button3_Click()Sub Button3_Click(ByVal sender As System.Object,_ ByVal e As System.EventArgs) Handles Button3.Click Dim Demohandler1 As DemoHandler Demohandler1 = AddressOf Button1_Click Demohandler1.Invoke(sender, e) Dim Demohandler2 As DemoHandler Demohandler2 = AddressOf Button2_Click Demohandler2(sender, e) End Sub Private Sub Button4_Click()Sub Button4_Click(ByVal sender As System.Object,_ ByVal e As System.EventArgs) Handles Button4.Click End Sub Private Sub Button5_Click()Sub Button5_Click(ByVal sender As System.Object,_ ByVal e As System.EventArgs) Handles Button5.Click End Sub Private Sub Form1_DoubleClick()Sub Form1_DoubleClick(ByVal sender As Object,_ ByVal e As System.EventArgs) Handles MyBase.DoubleClick, Button5.Click If TypeOf sender Is Button Then If MessageBox.Show("你確定退出嗎?", "退出提示",_ MessageBoxButtons.YesNo, MessageBoxIcon.Warning) = DialogResult.Yes Then Me.Close() Else : Exit Sub End If Else : Me.Close() End If End Sub End Class
Button1按鈕的click事件的代碼只需看看Handles子句,不僅有Button1.Click還有Button2.Click, Button4.Click,MSDN上說:在過程聲明結(jié)尾處使用Handles關(guān)鍵字將使其處理由使用 WithEvents 關(guān)鍵字聲明的對象變量所引發(fā)的事件。也可以在派生類中使用Handles關(guān)鍵字處理基類的事件。其實Handles子句允許任何與事件的參數(shù)簽名相符的過程來響應(yīng)這個事件。這實際上就是委托。在編譯時間,.NET Framework用你的事件名稱創(chuàng)建一個委托類,只是在結(jié)尾添加“EventHandler”字樣。換言之,事件是使用委托來實現(xiàn)的,委托是面向?qū)ο蠛瘮?shù)指針的一種形式,它允許通過對函數(shù)進(jìn)行引用的方法來間接地調(diào)用該函數(shù)。
雙擊set_Button1方法或其他set_...方法,你都可以看到有System.EventHandler類出現(xiàn)。.NET Framework 中的事件模型基于具有事件委托,System.EventHandler將事件與事件處理程序連接。
Button1的Click事件過程中的Select Case…End Select功能是根據(jù)點擊按鈕的名稱來選擇事件處理程序。
Button3的Click事件過程要好好看看的。如下:
語 句 釋 義
Dim Demohandler1 As DemoHandler:定義一個DemoHandler委托的實例,DemoHandler可以換成 EventHandler Demohandler1 = AddressOf Button1_Click:AddressOf可以認(rèn)為就是將該委托和Button1_Click綁定 Demohandler1.Invoke(sender, e):顯式使用委托的Invoke方法調(diào)用事件處理程序 Dim Demohandler2 As DemoHandler:定義一個DemoHandler委托的實例,DemoHandler2 Demohandler2 = AddressOf Button2_Click:同上AddressOf Demohandler2(sender, e):隱式使用委托的Invoke方法調(diào)用事件處理程序
Button4按鈕的click事件過程為空,因為在Button1_Click的Handles子句中已經(jīng)注冊,且由于它們的事件簽名完全一致,故調(diào)用Button1_Click事件處理過程。
Button5按鈕的click事件過程也為空,不要著急,下面的Form1_DoubleClick事件處理過程的Handles子句中注冊了Button5,所以Button5的click事件的事件處理程序調(diào)用Form1的DoubleClick事件的事件處理程序。
在Form1的DoubleClick事件處理過程使用對控件類型的判斷來選擇處理方式。
我不說你也看出來了,這樣寫代碼,就可以將一些本來需要重復(fù)多次的代碼省去,符合重構(gòu)的思想,使得代碼盡量簡約而由不失可讀性。
現(xiàn)實生活中委托別人辦的事能不能辦好取決于以下兩個方面:
1、是否委托給了合適的人;
2、是否把解決委托事件所需的正確和必要的信息傳遞給了它。
比如女兒委托我拿勺子,這個委托是相當(dāng)成功的,因為她委托給了我(人選合適)且明確要她的小勺(正確和必要的信息傳遞)。
對應(yīng)到.Net框架中的委托,一是要有委托對象,二是要簽名相符。
引用:
委托是用來處理其他語言(如 C++、Pascal 和 Modula)需用函數(shù)指針來處理的情況的。不過與 C++ 函數(shù)指針不同,委托是完全面對對象的;另外,C++ 指針僅指向成員函數(shù),而委托同時封裝了對象實例和方法。委托聲明定義一個從 System.Delegate 類派生的類。委托實例封裝一個調(diào)用列表,該列表列出一個或多個方法,其中每個方法均作為一個可調(diào)用實體來引用。對于實例方法,可調(diào)用實體由該方法和一個相關(guān)聯(lián)的實例組成。對于靜態(tài)方法,可調(diào)用實體僅由一個方法組成。用一個適當(dāng)?shù)膮?shù)集來調(diào)用一個委托實例,就是用此給定的參數(shù)集來調(diào)用該委托實例的每個可調(diào)用實體。
委托實例的一個有趣且有用的屬性是:它不知道也不關(guān)心它所封裝的方法所屬的類;它所關(guān)心的僅限于這些方法必須與委托的類型兼容。這使委托非常適合于“匿名”調(diào)用。——《C#語言規(guī)范》Scott Wiltamuth 和 Anders Hejlsberg
轉(zhuǎn)http://tech.it168.com/n/2006-04-12/200604121634437.shtml
|