總結:CLR Via C#(第15章):委託

來源:互聯網
上載者:User

委託

 

1、委託可確保回調方法是型別安全的;

2、委託可以順序調用多個方法,並支援靜態方法和執行個體方法;

3、委託封裝執行個體方法是非常有用的,因為對象內部的代碼可以訪問對象的執行個體方法成員,這就意味著對象可以維護一些狀態,並且在回調方法執行期間用到這種狀態;

4、委託實際上是類,因為編譯器會為委託產生一個完整的類,所以在可以定義類的地方,就可以定義委託;

5、Delegate類定義了兩個唯讀公用執行個體屬性:Target和Method;Target返回一個對象引用,該對象就是方法回調時要操作的那個對象,如果委派物件封裝了一個靜態方法,那麼Target將返回Null;Method屬性返回一個System.Reflection.MethodInfo對象引用(標識回調方法);

 

協變與反協變

協變(convariance):指的是一個方法返回從委託的傳回型別派生的一個類型;

反協變(contra-variance):指的是一個方法的參數類型可以是委託的參數類型的基底類型;

 

    internal delegate object MyCallback(int s);

 

    public class Delegate_covariance_contra_variance

    {

        private static string SomeMethod(object s)

        {

            Console.WriteLine(s.ToString());

            return s.ToString();

        }

 

        public static void Test()

        {

//Error:“SomeMethod(object)”的重載均與委託“MyCallback”不匹配

            MyCallback call = new MyCallback(SomeMethod);

 

            call(1);

        }

 

上面的代碼編譯時間會出錯,分析一下:

首先,SomeMethod的傳回型別(String)是繼承自委託傳回型別(Object),所以這種協變是允許的;

其次,SomeMethod的參數類型(Object)是委託的參數類型(int)的基類,符合

反協變的定義,但是這種反協變是無法通過編譯的,因為協變與反協變都不支援實值型別和Void:因為實值型別和void的儲存結構式變化的,而參考型別的儲存結構始終是一個指標;

         最後,修改方法就是將委託的參數類型改為參考型別。

internal delegate object MyCallback(string s);

 

對委託鏈調用進行更多控制

委託鏈調用要注意兩個問題:

1、 除最後一個傳回值之外,回調方法的所有傳回值都會被丟棄;

2、 如果被調用的委託中有一個拋出了異常或者堵塞了相當長一段時間,就會停止調用後續所有對象。

 

為此,MulticastDelegate類提供了一個執行個體方法GetInvocationList,

 

   private static String GetComponentStatusReport(GetStatus status) {

      // If the chain is empty, there抯is nothing to do.

      if (status == null) return null;

      // Use this to build the status report.

      StringBuilder report = new StringBuilder();

 

      // Get an array where each element is a delegate from the chain.

      Delegate[] arrayOfDelegates = status.GetInvocationList();

 

      // Iterate over each delegate in the array.

      foreach (GetStatus getStatus in arrayOfDelegates) {

 

         try {

            // Get a component's status string, and append it to the report.

            report.AppendFormat("{0} {1} {2}", getStatus(),getStatus.Target+":"+getStatus.Method, Environment.NewLine);

         }

         catch (InvalidOperationException e) {

            // Generate an error entry in the report for this component.

            Object component = getStatus.Target;

            report.AppendFormat(

               "Failed to get status from {1}{2}{0}   Error: {3}{0}{0}",

               Environment.NewLine,

               ((component == null) ? "" : component.GetType() + "."),

               getStatus.Method.Name, e.Message);

         }

      }

 

      // Return the consolidated report to the caller.

      return report.ToString();

   }

 

C#為委託提供的文法便利

主要介紹了委託的簡便寫法,這裡有一個定義匿名方法(anonymous method),要注意三點:

1、 在編寫匿名方法的時候,在代碼中的delegate關鍵字後加入這個指定名稱(Object obj);

internal sealed class AClass {

   private static void CallbackWithoutNewingADelegateObject() {

      ThreadPool.QueueUserWorkItem(

         delegate(Object obj) { Console.WriteLine(obj); }, 5);

   }

}

2、 匿名方法標識為private,這會禁止在類型內部定義的任何代碼訪問這個方法;

匿名方法標識為static,這是因為代碼沒有訪問任何執行個體方法成員,不過,代碼可以引用類中定義的靜態欄位或靜態方法;

internal sealed class AClass {

 

    private static string m_str;

 

   private static void CallbackWithoutNewingADelegateObject() {

      ThreadPool.QueueUserWorkItem(

         delegate(Object obj) { Console.WriteLine( m_str+":"+obj); }, 5);

   }

}

 

3、 如果CallbackWithoutNewingADelegateObject方法不是靜態,那麼匿名方法的代碼就可以包含對執行個體成員的引用;

internal sealed class AClass {

 

    private int m_i;

 

    private void CallbackWithoutNewingADelegateObject1()

    {

        ThreadPool.QueueUserWorkItem(

           delegate(Object obj) { Console.WriteLine(m_i + ":" + obj); }, 5);

    }

}

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.