談及到C#的基本特性,“委托”是不得不去了解和深入分析的一個(gè)特性。對(duì)于大多數(shù)剛?cè)腴T(mén)的程序員談到“委托”時(shí),都會(huì)想到“將方法作為方法的參數(shù)進(jìn)行傳遞”,很多時(shí)候都只是知道簡(jiǎn)單的定義,主要是因?yàn)椤拔小痹诶斫馍嫌休^其他特性比較難的地方。在本次說(shuō)明中,不會(huì)將委托的簡(jiǎn)單聲明和調(diào)用作為重點(diǎn)。
“委托”不需要直接定義一個(gè)要執(zhí)行的行為,而是將這個(gè)行為用某種方法“包含”在一個(gè)對(duì)象中。這個(gè)對(duì)象可以像其他任何對(duì)象那樣使用。在該對(duì)象中,可以執(zhí)行封裝的操作。可以選擇將委托看作之定義了一個(gè)方法的接口,將委托的實(shí)例看作實(shí)現(xiàn)了那個(gè)接口的對(duì)象。
在“委托”的相關(guān)定義中,我們可以不難看出,“委托與方法“相比較于“接口與類(lèi)”有著設(shè)計(jì)理念上的相似部分,產(chǎn)生的背景源于”設(shè)計(jì)原則“中的”開(kāi)放-封閉原則“,”開(kāi)放-封閉“原則:是說(shuō)軟件實(shí)體(類(lèi),模塊,函數(shù)等等)應(yīng)該可以擴(kuò)展,但是不可修改。換一種說(shuō)法可能更好的理解”對(duì)于擴(kuò)展是開(kāi)放的,對(duì)于更改是封閉的“,面對(duì)新的需求,對(duì)于程序的改動(dòng)是通過(guò)增加新的代碼進(jìn)行的,而不是更改現(xiàn)有的代碼。
在C#中委托用delegate關(guān)鍵字定義,使用new操作符構(gòu)造委托實(shí)例,采用傳統(tǒng)的方法調(diào)用語(yǔ)法來(lái)回調(diào)函數(shù)(只是要用引用了委托對(duì)象的一個(gè)變量代替方法名)。在C#中,委托在編譯的時(shí)候會(huì)被編譯成類(lèi)。對(duì)于委托的一個(gè)說(shuō)明:委托是一個(gè)類(lèi),它定義了方法的類(lèi)型,使得可以將方法當(dāng)作另一個(gè)方法的參數(shù)來(lái)進(jìn)行傳遞。委托類(lèi)既可嵌套在一個(gè)類(lèi)型中定義,也可以在全局范圍內(nèi)定義。由于委托是類(lèi),凡是可以定義類(lèi)的地方,都可以定義委托。
接下來(lái)我們來(lái)看一下”委托“的組成,需要滿(mǎn)足的條件:
1.聲明委托類(lèi)型。
2.必須有一個(gè)方法包含了要執(zhí)行的代碼。
3.必須創(chuàng)建一個(gè)委托實(shí)例。
4.必須調(diào)用委托實(shí)例。
接下來(lái)大致的了解一下上面所提出的4項(xiàng)條件:
委托類(lèi)型實(shí)際上只是參數(shù)類(lèi)型的一個(gè)列表以及返回類(lèi)型。規(guī)定了類(lèi)型的實(shí)例能表示的操作。在調(diào)用一個(gè)委托實(shí)例的時(shí)候,必須保證使用的參數(shù)完全匹配,而且能以指定的方式使用返回值。對(duì)于委托實(shí)例的創(chuàng)建,取決于操作使用實(shí)例方法還是靜態(tài)方法(如果操作是靜態(tài)方法,指定類(lèi)型名稱(chēng)就可以,如果是操作實(shí)例方法,需要先創(chuàng)建類(lèi)型的實(shí)例)。對(duì)于委托的調(diào)用,可以直接調(diào)用委托的實(shí)例的方法就可以完成對(duì)應(yīng)的操作。
以上談及了”委托“的定義和組成,接下來(lái)我們來(lái)了解一下如何將方法綁定到”委托“上,以及委托的合并和刪除。
可以將多個(gè)方法賦給同一個(gè)委托,委托實(shí)例實(shí)際有一個(gè)操作列表與之關(guān)聯(lián)。在System.Delegate類(lèi)型中提供了兩個(gè)靜態(tài)方法Combine()和Remove()負(fù)責(zé)委托實(shí)例的新增和刪除操作。但是在我們的實(shí)際開(kāi)發(fā)中,較多的采用-=和+=操作符。
在FCL中,所有的委托類(lèi)型都派生自MulticastDelegate,該類(lèi)型在System.MulticastDelegate類(lèi)型中。
具體來(lái)看一下Combine()方法的底層實(shí)現(xiàn)代碼:
[System.Runtime.InteropServices.ComVisible(true)] public static Delegate Combine(<