C# delegate


 .Net 中的委托類似於 C 或 C++ 中的函數指針。使用委托使程序員可以將方法引用封裝在委托對象內。然后可以將該委托對象傳遞給可調用所引用方法的代碼,而不必在編譯時知道將調用哪個方法。與 C 或 C++ 中的函數指針不同,委托是面向對象、類型安全的,並且是安全的。

  委托聲明定義一種類型,它用一組特定的參數以及返回類型封裝方法。對於靜態方法,委托對象封裝要調用的方法。對於實例方法,委托對象同時封裝一個實例和該實例上的一個方法。如果您有一個委托對象和一組適當的參數,則可以用這些參數調用該委托。委托的一個有趣且有用的屬性是,它不知道或不關心自己引用的對象的類。任何對象都可以;只是方法的參數類型和返回類型必須與委托的參數類型和返回類型相匹配。這使得委托完全適合“匿名”調用。

      在任何地方都可以使用Delegates
在這一點上,也許你只知道有這樣一回事,但卻沒有察覺它在你的程序中的應用。雖然你沒有建立自己的delegates,但如果經常使用事件時你會使用到它們。一個極好的例子就是ASP.NET中使用的事件。在后台使用的Delegates圍繞着事件工作。事件使用一個標記,你也可以在一個線程結構中找到delegates。

Delegate 和 interface

你必須注意的另一個點是一個delegate和一個接口之間的相似性,因為它們都將規范和執行分離開來。它們允許開發人員建立與規范相符合的執行。除此之外,方法標記必須是被指定和相兼容。

所以,你什么時候使用接口?以及你什么時候使用delegates?微軟提供了以下的指導思想。

Delegates:
調用一個單一方法。 一個類要進行方法規范(method specification)的多種執行。 使用一個靜態方法來執行規范。 想獲得類似事件設計的模式。 調用者沒有必要知道或獲得方法定義的對象。 執行的提供者想將規范的執行“分發”成一些選擇性的部分。

interface:

規范指定一套即將被調用的方法。 特別的,一個類只執行規范一次。 接口的調用者想通過接口類型以獲得其它接口或類。

 

下面我們用示例來理解一下吧!.....................O(∩_∩)O

示例1

BookDB是一個書籍數據庫、他公開了ProcessPaperbackBooks 方法、並且每本平裝書都調用一個委托ProcessBookDelegate、從而得到書籍標題和平均價格

Code

 1 using System;
2 namespace Bookstore
3 {
4 using System.Collections;
5 public struct Book
6 {
7 public string Title; //標題
8 public string Author; // 作者
9 public decimal Price; // 價格
10 public bool Paperback; // 是否是平裝書籍
11 public Book(string title, string author, decimal price, bool paperBack)
12 {
13 Title = title;
14 Author = author;
15 Price = price;
16 Paperback = paperBack;
17 }
18 }
19 //聲明委托 參數是book
20 public delegate void ProcessBookDelegate(Book book);
21
22 // 模擬書籍數據庫
23 public class BookDB
24 {
25 ArrayList list = new ArrayList();
26 //添加
27 public void AddBook(string title, string author, decimal price, bool paperBack)
28 {
29 list.Add(new Book(title, author, price, paperBack));
30 }
31 // 處理平裝書籍
32 public void ProcessPaperbackBooks(ProcessBookDelegate processBook)
33 {
34 foreach (Book b in list)
35 {
36 if (b.Paperback)//過濾平裝書籍
37 processBook(b);
38 }
39 }
40 }
41 }
42 //書籍平均價格
43 namespace BookTestClient
44 {
45 using Bookstore;
46 class PriceTotaller
47 {
48 int countBooks = 0;
49 decimal priceBooks = 0.0m;
50 internal void AddBookToTotal(Book book)
51 {
52 countBooks += 1;
53 priceBooks += book.Price;
54 }
55 internal decimal AveragePrice()
56 {
57 return priceBooks / countBooks;
58 }
59 }
60 class Test
61 {
62 //打印評價書籍標題
63 static void PrintTitle(Book b)
64 {
65 Console.WriteLine(" {0}", b.Title);
66 }
67 static void Main()
68 {
69 Console.WriteLine("創建書籍數據庫");
70 BookDB bookDB = new BookDB();
71 AddBooks(bookDB);
72 Console.WriteLine("增加書籍完畢");
73 Console.WriteLine("所有平裝書名");
74 bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));
75 PriceTotaller totaller = new PriceTotaller();
76 bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));
77 Console.WriteLine("評價書籍平均價格是: ${0:#.##}",
78 totaller.AveragePrice());
79 }
80 static void AddBooks(BookDB bookDB)
81 {
82 bookDB.AddBook("C# 設計模式","X.Y", 19.95m, true);
83 bookDB.AddBook("人月神話 ","X.Y", 39.95m, true);
84 bookDB.AddBook("大話設計模式", "X.Y", 129.95m, false);
85 bookDB.AddBook("精通C#", "X.Y", 12.00m, true);
86 }
87 }
88 }

效果圖

 

 示例2

 委托是可以用"+"和"-"來添加和移除的、但是要滿足兩個條件。條件一:必須是相同類型的委托、條件二:必須都是void返回值

Code

 1 using System;
2 delegate void MyDelegate(string s);
3 class MyClass
4 {
5 public static void Hello(string s)
6 {
7 Console.WriteLine(" Hello, {0}!", s);
8 }
9 public static void Goodbye(string s)
10 {
11 Console.WriteLine(" Goodbye, {0}!", s);
12 }
13 public static void Main()
14 {
15 MyDelegate a, b, c, d;
16
17 a = new MyDelegate(Hello);
18
19 b = new MyDelegate(Goodbye);
20
21 c = a + b;
22
23 d = c - a;
24 Console.WriteLine("調用 delegate a:");
25 a("A");
26 Console.WriteLine("調用 delegate b:");
27 b("B");
28 Console.WriteLine("調用 delegate c:");
29 c("C");
30 Console.WriteLine("調用 delegate d:");
31 d("D");
32 }
33 }

效果圖


免責聲明!

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



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