|
說(shuō)起鏈表大家都很熟悉,說(shuō)起委托相信大部分的.NET程序員都也很了解。在平時(shí)的開發(fā)過(guò)程中經(jīng)常會(huì)用到這兩種技術(shù),只不過(guò)鏈表在.NET里面已經(jīng)被封裝了,讓我們用起來(lái)更加的方便就是集合類型Collection。在某些時(shí)候我們有必要要了解這些方便而又快捷的背后是怎樣封裝的,委托是一種特殊的類型,在.NET里面是用來(lái)作為方法的一種封裝。在一些非托管的代碼中如C++就沒有這么幸運(yùn)了,我們要面對(duì)是一些復(fù)雜的地址變換、鏈表的指針維護(hù)、內(nèi)存的取址等等。微軟一向都是人性化模仿的對(duì)象,不管是他的操作系統(tǒng)還是開發(fā)平臺(tái)IDE做的都很舒服。可能有的人會(huì)說(shuō)把程序員這么崇高而又神秘的職業(yè)該大眾化了,是人都會(huì)寫程序。這種問(wèn)題大家仁者見仁,智者見智了。
今天我要說(shuō)的就是.NET中的委托鏈,也許這個(gè)技術(shù)名詞見的人很少,但是概念大家都能從字面上理解出來(lái),那就是委托與鏈表的關(guān)系。簡(jiǎn)單點(diǎn)就是委托通過(guò)鏈表的方式將其保存,然后依次調(diào)用,關(guān)于委托與事件的可以參照本人的“委托與事件”文章。委托是指向方法的指針,將方法以對(duì)象的方式包裝起來(lái),方便、安全、異步的調(diào)用,在異步方面都是CLR通過(guò)后臺(tái)線程去處理,我們不需要關(guān)心一些線程調(diào)度互斥等問(wèn)題,特殊情況下也需要我們自己去從頭封裝。委托是一種類型,通過(guò)實(shí)例化多個(gè)委托實(shí)例去封裝要調(diào)用的方法,在程序運(yùn)行過(guò)程中每一個(gè)方法是被壓入棧的數(shù)據(jù)結(jié)構(gòu)中的,在調(diào)用之前先要確定方法的地址,所有通過(guò)引用類型將方法獨(dú)立出來(lái),方便尋找和調(diào)用。當(dāng)多個(gè)委托實(shí)例聚集在一起的時(shí)候就形成了委托鏈這么一個(gè)數(shù)據(jù)結(jié)構(gòu),比如在我們經(jīng)常使用的Button中一個(gè)Click事件,我們會(huì)通過(guò):Button.Click+=New 委托類型(方法1)將一個(gè)委托實(shí)例加入到委托鏈表中去,我繼續(xù)添加一個(gè)方法到鏈表中去Button.Click+=New 委托類型(方法2),這個(gè)時(shí)候在委托鏈表中就有了兩個(gè)委托實(shí)例了,也就是兩個(gè)方法的調(diào)用。鏈表是有順序的,方法2在方法1后面,代碼的調(diào)用順序就是先調(diào)用方法1,然后將處理結(jié)果再帶入到方法2中,處理依次進(jìn)行,這樣就形成了對(duì)委托鏈的整體調(diào)用。在使用時(shí)有一些細(xì)節(jié)需要注意也是性能的問(wèn)題,“代碼永遠(yuǎn)是危害程序性能的罪魁禍?zhǔn)?rdquo;,在上述代碼中Btton.Click+=New 委托類型(方法1),可以寫成Button.Click+=方法1,這樣就減少了一個(gè)委托實(shí)例的內(nèi)存分配,系統(tǒng)將使用順序表保存調(diào)用的方法,而不是鏈表,鏈表和順序表在性能的區(qū)別我想學(xué)過(guò)《數(shù)據(jù)結(jié)構(gòu)》的人都知道。當(dāng)不需要使用鏈表中的某個(gè)方法時(shí),可以通過(guò)委托移除表達(dá)式將方法從委托鏈表中移除,Button.Click-=方法1,我已經(jīng)將方法1從委托鏈表中移除,當(dāng)下次調(diào)用時(shí),代碼是不會(huì)走到方法1中的,在我們開發(fā)過(guò)程中經(jīng)常會(huì)遇到這樣的情況:一個(gè)事件發(fā)生了我要調(diào)用N個(gè)方法,但是我并不能控制這種執(zhí)行順序,這個(gè)時(shí)候我們就可以將方法從鏈表中移除或者添加,很方便的控制委托鏈中的方法執(zhí)行前后順序。也會(huì)遇到這種情況,我有十個(gè)方法用來(lái)處理程序的邏輯,但是這十個(gè)方法不是死的,我需要根據(jù)不同的條件,從這十個(gè)方法中動(dòng)態(tài)跳轉(zhuǎn)到其他的邏輯處理中,然后再回到該方法,程序永遠(yuǎn)不會(huì)脫離這十個(gè)方法,這個(gè)時(shí)候我們就需要用到委托參數(shù)了,這個(gè)時(shí)候我們需要定義一種類型用來(lái)在委托鏈表中傳遞,方法通過(guò)判斷這個(gè)類型的實(shí)例的狀態(tài),確定是否繼續(xù)向下傳遞;
圖1:
這個(gè)委托鏈中有4個(gè)方法,當(dāng)我執(zhí)行到方法2的時(shí)候我需要判斷用戶的輸入是否正確,是否讓后面的方法在繼續(xù)執(zhí)行:
public class Class1
{
/// <summary>
/// 委托類型
/// </summary>
/// <param name="ismove">是否向下執(zhí)行的標(biāo)識(shí)</param>
public delegate void Print(ref string ismove);
/// <summary>
/// 委托實(shí)例
/// </summary>
Print p;
/// <summary>
///默認(rèn)構(gòu)造函數(shù)
/// </summary>
public Class1()
{
//添加四個(gè)方法
Print p = new Print(method1);//第一個(gè)方法用來(lái)實(shí)例化委托第一個(gè)實(shí)例
p += method2;
p += method3;
p += method4;
}
/// <summary>
/// 開始執(zhí)行委托鏈
/// </summary>
/// <returns></returns>
public string run()
{
string ismove = "yes";
p(ref ismove);
return ismove;
}
public void method1(ref string ismove)
{
if (ismove == "yes")//判斷是否要繼續(xù)向下執(zhí)行
{
}
}
public void method2(ref string ismove)
{
if (ismove == "yes")//判斷是否要繼續(xù)向下執(zhí)行
{
//我這里執(zhí)行出了問(wèn)題,不想繼續(xù)向下執(zhí)行了
ismove = "no";//后面的所有方法都不會(huì)執(zhí)行
}
}
public void method3(ref string ismove)
{
if (ismove == "yes")//判斷是否要繼續(xù)向下執(zhí)行
{
}
}
public void method4(ref string ismove)
{
if (ismove == "yes")//判斷是否要繼續(xù)向下執(zhí)行
{
}
}
}
NET技術(shù):.NET簡(jiǎn)談委托鏈,轉(zhuǎn)載需保留來(lái)源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。