[C#] C# 知識回顧 - 委托 delegate


C# 知識回顧 - 委托 delegate

【博主】反骨仔    【原文】http://www.cnblogs.com/liqingwen/p/6031892.html

目錄

 

What's 委托

  delegate 一種自定義的引用類型,它包含了特定的參數列表和返回類型

  使用委托時,只需要對應的方法的簽名和返回類型兼容即可,無論是實例方法,抑或是靜態方法。通過調用委托的實例就相當於調用方法本身,因為委托存儲的是一個方法列表,調用委托的實例就相當於依次調用方法列表的內容。委托它將方法作為參數進行傳遞給了其它方法,我們常用的事件處理程序就是通過委托調用的方法,也是一種觀察者模式的體現。

 

  下面的示例演示了一個委托聲明:

public delegate int Del(int x, int y);

  

  使用委托的要求是:方法簽名與返回類型兼容。可以是靜態方法,也可以是實例方法。  

 

   【備注】方法的簽名 不包括返回值

 

委托的特點

  • 類型安全,類似於 C 和 C++ 中的函數指針。

  • 可將方法作為參數進行傳遞。

  • 可用於定義回調方法。

  • 委托可以鏈接在一起;例如,可以對一個事件調用多個方法。

  • 方法不必與委托類型完全匹配。

 

使用委托

  委托,一種類型,它是安全的,自定義的,委托的名稱就決定了這個委托是什么類型。

    //該委托可以封裝 “,參數類型 string,返回類型 void” 的方法 
    public delegate void MyDel(string message);

 

  委托的實例對象通常使用兩種方式進行構建,直接使用類的方法名,或者使用 Lambda 表達式,當然匿名方法也可以。

  在調用委托的時刻,我們將傳遞到委托的參數會繼續傳遞到委托列表的方法中。如果委托列表中包含返回值的話,會將最后一個返回值返回給調用方。也就是該委托對象調用完畢的返回值。

 1     //該委托名為 MyDel,可以封裝 “參數類型 string,返回值類型 void” 的方法 
 2     public delegate void MyDel(string message);
 3 
 4     class Program
 5     {
 6         static void Main(string[] args)
 7         {
 8             //實例化委托
 9             MyDel del = Print;
10             //調用委托
11             del("Hi");
12 
13             Console.Read();
14         }
15 
16         /// <summary>
17         /// 打印文本
18         /// </summary>
19         /// <remarks>這是一個可用於 MyDel 委托的方法</remarks>
20         /// <param name="message"></param>
21         private static void Print(string message)
22         {
23             Console.WriteLine(message);
24         }
25     }

  委托的關鍵字是 delegate,它派生自 Delegate 類,也是 sealed,即密封類,不能作為基類再繼續派生。

  異步回調:允許以方法的形式作為參數形式進行傳遞,並在稍后進行該委托的調用。通過這個形式使用的委托,調用方不需要知道方法的具體實現,只是簡單的把它當做一個功能即可,這類似接口的封裝。

 
  簡單的異步回調方法演示:
 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             MyDel del = Print;
 6             CallbackMethod(100, 150, del);  //將委托傳遞到 CallbackMethod 方法
 7 
 8             Console.Read();
 9         }
10 
11         /// <summary>
12         /// 回調方法
13         /// </summary>
14         /// <param name="m"></param>
15         /// <param name="n"></param>
16         /// <param name="del"></param>
17         private static void CallbackMethod(int m, int n, MyDel del)
18         {
19             del((m + n).ToString());
20         }
21 
22         private static void Print(string message)
23         {
24             Console.WriteLine(message);
25         }
26     }

 

  在這里的 CallbackMethod 作用是,調用委托,因為它包含的是 Print() 方法的調用,所以只需要傳遞對應的 string 類型作為參數即可。

 

  我們在創建委托的時候,你可以選擇使用的是實例方法或者是靜態方法。當你使用的是實例方法時,該委托對象會同時引用該實例的對象及它的方法。委托並不關心應用引用對象的類型,它關心的是,方法簽名和返回值兼容,即可。不過,如果你創建委托對象包含的是靜態方法的時候,它是只引用該方法的。

  使用 += 可以把多個方法添加到一個委托對象的調用列表中,調用一次委托,相當於一次性調用一堆方法。

 1     //該委托可以封裝 “名 MyDel,參數類型 string,返回值類型 void” 的方法 
 2     public delegate void MyDel(string message);
 3 
 4     class MyClass
 5     {
 6         public void Print1(string message)
 7         {
 8             Console.WriteLine($"{message} - {nameof(Print1)}");
 9         }
10 
11         public void Print2(string message)
12         {
13             Console.WriteLine($"{message} - {nameof(Print2)}");
14         }
15     }
16 
17     class Program
18     {
19         static void Main(string[] args)
20         {
21             var myClass = new MyClass();
22             MyDel del1 = myClass.Print1;
23             MyDel del2 = myClass.Print2;
24             MyDel del3 = Print;
25 
26             var del = del1 + del2;
27             del += del3;    //這里使用 +=
28             del("Hi!");
29 
30             Console.Read();
31         }
32 
33         private static void Print(string message)
34         {
35             Console.WriteLine($"{message} - {nameof(Print)}");
36         }
37     }

   委托對象 del,他內部存儲的是一個包含三個方法的調用列表(Print1、Print2 和 Print),在你調用 del 對象時,調用列表中的方法會依次調用。

  

  多播委托:一個委托對象調用多個方法,使用 +=。

  若要從委托對象的調用列表中移除方法,需要使用 -=。

 

 1         static void Main(string[] args)
 2         {
 3             var myClass = new MyClass();
 4             MyDel del1 = myClass.Print1;
 5             MyDel del2 = myClass.Print2;
 6             MyDel del3 = Print;
 7 
 8             var del = del1 + del2;
 9             del += del3;    //使用 +=
10             del("Hi!");
11 
12             Console.WriteLine("======分割線======");
13 
14             del -= del2;    //使用 -=
15             del("Hi!");
16 
17             Console.Read();
18         }

 

  你也可以編寫一些方法獲取調用列表中方法的數量:

 1         static void Main(string[] args)
 2         {
 3             var myClass = new MyClass();
 4             MyDel del1 = myClass.Print1;
 5             MyDel del2 = myClass.Print2;
 6             MyDel del3 = Print;
 7 
 8             var del = del1 + del2;
 9             del += del3;    //使用 +=
10             //del("Hi!");
11 
12             var count = del.GetInvocationList().Length; //獲取委托調用列表中方法的數量
13             Console.WriteLine(count);
14 
15             Console.WriteLine("======分割線======");
16 
17             del -= del2;    //使用 -=
18             //del("Hi!");
19 
20             count = del.GetInvocationList().Length; //獲取委托調用列表中方法的數量
21             Console.WriteLine(count);
22 
23             Console.Read();
24         }

 

  多播委托派生自 MulticastDelegate,也是繼承自 Delegate的,常用於事件處理中。

 

傳送門

  《C# 知識回顧 - 序列化

  《C# 知識回顧 - 表達式樹 Expression Trees

 

 


【參考】https://msdn.microsoft.com/zh-cn/library/windows/apps/ms173171(v=vs.120).aspx

【參考】微軟官方文檔


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM