明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

第12章 委托[《.net框架程序設(shè)計(jì)》讀書筆記]

[摘要]第十二章 委托一、 委托的使用靜態(tài)委托和實(shí)例委托,使用方法類似,這里給出一個(gè)使用可變參數(shù)委托的例子:using System; public class DelCls ...
第十二章 委托

一、 委托的使用

靜態(tài)委托和實(shí)例委托,使用方法類似,這里給出一個(gè)使用可變參數(shù)委托的例子:

using System;



public class DelCls

{

public delegate void DelDef(params string[] strParams);



public static void CallDel(DelDef dd)

{

if(dd != null) //請務(wù)必在此處進(jìn)行判斷,這是個(gè)好習(xí)慣

{

dd("Hello", "world");

}

}

}



public class DelIns

{

//聲明為private(私有)成員并不影響在類型內(nèi)部使用委托

private static void ClsCallStr(params string[] strParams) //類型方法

{

//將字符串?dāng)?shù)組并順序輸出

foreach(string str in strParams)

{

Console.Write("{0} ", str);

}

Console.WriteLine();

}



public void InsCallStr(params string[] strParams) //實(shí)例方法

{

//將字符串?dāng)?shù)組并反序輸出

for(int i = strParams.Length - 1; i >= 0; i --)

{

Console.Write("{0} ", strParams[i]);

}



Console.WriteLine();

}



public static void Main()

{

DelIns di = new DelIns();



DelCls.DelDef dd = null;

Console.WriteLine("combine two delegate:");

dd += new DelCls.DelDef(DelIns.ClsCallStr);

dd += new DelCls.DelDef(di.InsCallStr);

DelCls.CallDel(dd);



Console.WriteLine("remove the first delegate:");

dd -= new DelCls.DelDef(DelIns.ClsCallStr);

DelCls.CallDel(dd);

}

}



/*運(yùn)行結(jié)果

combine two delegate:

Hello world

world Hello

remove the first delegate:

world Hello

*/

在C#中使用委托方法:

l 創(chuàng)建委托所使用的方法必須和委托聲明相一致(參數(shù)列表、返回值都一致)

l 利用 +=、-=來進(jìn)行委托的鏈接或取消鏈接或直接使用Delegate.Combine和Delegate.Remove方法來實(shí)現(xiàn)

l 使用MulticastDelegate的實(shí)例方法GetInvocationList()來獲取委托鏈中所有的委托



二、 委托揭秘

所有的委托都繼承自MulticastDelegate,編譯器在編譯時(shí)刻為委托的聲明生成了一個(gè)完整的委托類,重點(diǎn)注意其中的一些成員:

ü 構(gòu)造函數(shù),傳入委托的目標(biāo)對象(實(shí)例)及指向回調(diào)方法的整數(shù)

ü 繼承自MulticastDelegate的_target(System.Object)字段

ü 繼承自MulticastDelegate的_methodPtr(System.Int32)字段

ü 繼承自MulticastDelegate的_prev(System.MulticastDelegaet)字段

ü 生成的與方法聲明相一致Invoke函數(shù)用以調(diào)用方法

可利用MulticastDelegate中的Method及Target屬性來考察_methodPtr及_target字段的性質(zhì)。

關(guān)于編譯器生成的委托類及Invoke方法的調(diào)用情況,可通過使用ILDAsm.exe查看執(zhí)行文件的IL代碼獲得

將上例中類型DelIns中的Main方法作如下修改,以實(shí)驗(yàn)GetInvocationList及MulticastDelegate中屬性的使用:

public class DelIns

{



public static void Main()

{



Delegate[] arrDel = dd.GetInvocationList();

foreach(DelCls.DelDef d in arrDel)

{

Console.WriteLine("Object type: {0}, Method name: {1}",

(d.Target != null) ? d.Target.GetType().ToString() : "null",

d.Method.Name);

}



}



}

/*運(yùn)行結(jié)果



Object type: null, Method name: ClsCallStr

Object type: DelIns, Method name: InsCallStr



*/

三、 委托判等

首先判斷_methodPtr及_target字段是否相等,若不等則返回false;

若相等,繼續(xù)判斷_prev是否為null(指向委托鏈頭部的委托),若為null,則相等返回true;

若不等,繼而判斷委托鏈上所有委托對象,重復(fù)上述步驟。



可見牽涉到委托鏈的時(shí)候是個(gè)遞歸判斷的過程。

四、 委托鏈

l 首先被加入到委托鏈中的委托位于委托鏈的尾部,但首先被調(diào)用,這是因?yàn)镮nvoke中利用遞歸對委托函數(shù)進(jìn)行調(diào)用,這樣位于頭部的委托最后被調(diào)用。

l 委托調(diào)用后的返回值,只是最后一次被調(diào)用方法的返回值,即委托鏈頭部委托的返回值

l 每調(diào)用一次Remove方法只刪除匹配的第一個(gè)委托鏈

五、 委托與反射

以下是.net framework sdk文檔提供的Delegate.CreateDelegate方法列表:

創(chuàng)建指定類型的委托以表示指定的靜態(tài)方法。

[C#] public static Delegate CreateDelegate(Type, MethodInfo);

創(chuàng)建指定類型的委托,該委托表示要對指定的類實(shí)例調(diào)用的指定實(shí)例方法。

[C#] public static Delegate CreateDelegate(Type, object, string);

創(chuàng)建指定類型的委托,該委托表示指定類的指定靜態(tài)方法。

[C#] public static Delegate CreateDelegate(Type, Type, string);

創(chuàng)建指定類型的委托,該委托表示要按指定的大小寫敏感度對指定類實(shí)例調(diào)用的指定實(shí)例方法。

[C#] public static Delegate CreateDelegate(Type, object, string, bool);



下面的示例演示了創(chuàng)建靜態(tài)方法委托、實(shí)例方法委托以及動態(tài)調(diào)用委托:

using System;

using System.Reflection;



public class DelReflection

{

public delegate void GoGo(string strPam, Int32 nPam);



public static void ClsGo(string strPam, Int32 nPam)

{

Console.WriteLine("In class, String:{0}, Int32:{1}", strPam, nPam);

}



public void InsGo(string strPam, Int32 nPam)

{

Console.WriteLine("In instance, String:{0}, Int32:{1}", strPam, nPam);

}



public static void Main()

{

Delegate d = null;



d = Delegate.CreateDelegate(typeof(GoGo), typeof(DelReflection), "ClsGo");

if(d != null)

d.DynamicInvoke(new Object[]{"Hello", 45});



DelReflection dr = new DelReflection();

d = Delegate.CreateDelegate(typeof(GoGo), dr, "InsGo");

if(d != null)

d.DynamicInvoke(new Object[]{"Hello", 45});

}

}

/*運(yùn)行結(jié)果

In class, String:Hello, Int32:45

In instance, String:Hello, Int32:45