委託[《.net架構程式設計》讀書筆記

來源:互聯網
上載者:User

第十七章 委託

一、             委託的使用

靜態委託和執行個體委託,使用方法類似,這裡給出一個使用可變參數委託的例子:

using System;

 

public class DelCls

{

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

 

       public static void CallDel(DelDef dd)

       {

              if(dd != null)   //請務必在此處進行判斷,這是個好習慣

              {

                     dd("Hello", "world");

              }

       }

}

 

public class DelIns

{

       //聲明為private(私人)成員並不影響在類型內部使用委託

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

       {

              //將字串數組並順序輸出

              foreach(string str in strParams)

              {

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

              }

              Console.WriteLine();

       }

      

       public void InsCallStr(params string[] strParams)              //執行個體方法

       {

              //將字串數組並反序輸出

              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);

       }

}

 

/*運行結果

combine two delegate:

Hello world

world Hello

remove the first delegate:

world Hello

*/

在C#中使用委託方法:

l         建立委託所使用的方法必須和委託聲明相一致(參數列表、傳回值都一致)

l         利用 +=、-=來進行委託的連結或取消連結或直接使用Delegate.Combine和Delegate.Remove方法來實現

l         使用MulticastDelegate的執行個體方法GetInvocationList()來擷取委託鏈中所有的委託

 

二、             委託揭秘

所有的委託都繼承自MulticastDelegate,編譯器在編譯時間刻為委託的聲明產生了一個完整的委託類,重點注意其中的一些成員:

ü         建構函式,傳入委託的目標對象(執行個體)及指向回調方法的整數

ü         繼承自MulticastDelegate的_target(System.Object)欄位

ü         繼承自MulticastDelegate的_methodPtr(System.Int32)欄位

ü         繼承自MulticastDelegate的_prev(System.MulticastDelegaet)欄位

ü         產生的與方法聲明相一致Invoke函數用以調用方法

可利用MulticastDelegate中的Method及Target屬性來考察_methodPtr及_target欄位的性質。

關於編譯器產生的委託類及Invoke方法的調用情況,可通過使用ILDAsm.exe查看執行檔案的IL代碼獲得

將上例中類型DelIns中的Main方法作如下修改,以實驗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);  

              }

              …

       }

}

/*運行結果

Object type: null, Method name: ClsCallStr

Object type: DelIns, Method name: InsCallStr

*/

三、             委託判等

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

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

若不等,繼而判斷委託鏈上所有委派物件,重複上述步驟。

 

可見牽涉到委託鏈的時候是個遞迴判斷的過程。

四、             委託鏈

l         首先被加入到委託鏈中的委託位於委託鏈的尾部,但首先被調用,這是因為Invoke中利用遞迴對委託函數進行調用,這樣位於頭部的委託最後被調用。

l         委託調用後的傳回值,只是最後一次被呼叫者法的傳回值,即委託鏈頭部委託的傳回值

l         每調用一次Remove方法只刪除匹配的第一個委託鏈

五、             委託與反射

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

建立指定類型的委託以表示指定的靜態方法。

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

建立指定類型的委託,該委託表示要對指定的類執行個體調用的指定執行個體方法。

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

建立指定類型的委託,該委託表示指定類的指定靜態方法。

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

建立指定類型的委託,該委託表示要按指定的大小寫敏感度對指定類執行個體調用的指定執行個體方法。

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

 

下面的樣本示範了建立靜態方法委託、執行個體方法委託以及動態調用委託:

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});          

       }

}

/*運行結果

In class, String:Hello, Int32:45

In instance, String:Hello, Int32:45

*/

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.