亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

C#中的委托與事件[翻譯]

2019-11-18 19:04:25
字體:
來源:轉載
供稿:網友

委托與事件
    Ganesh Nataraj最近寫了一篇解釋委托與事件的文章,在坊間流傳較廣,今天翻譯成中文與大家共享,如有不妥之處,歡迎留言討論。
    C#中的委托類似于C或C++中的函數指針。程序設計人員可以使用委托將方法的引用壓縮到委托對象中,委托對象能被傳遞給調用該方法引用的代碼而無須知道哪個方法將在編譯時被調用。與C或C++中的指針不同的是,委托是面向對象的、類型安全的、受保護的。
    委托聲明時定義一個返回壓縮方法的類型,其中包含一組特定的描述和返回類型。對于靜態方法而言,委托對象壓縮其調用的方法。對于實例方法(instance methods)而言,委托對象將壓縮一個實例和實例的一個方法。如果一個委托對象有一組適當的描述,可以調用帶描述的委托。
    委托有趣而實用的一個特征就是它不用知道也無需關心它引用對象的類,任何對象都可以,關鍵的是方法的描述類型和引用類型要與委托的匹配。這使委托特別適合一些匿名的請求。
注意:委托以調用方的安全許可身份運行,而不是以聲明方的許可運行。
    下面有兩個委托的示例:
    例1向大家說明如何聲明、實例化和調用一個委托;
    例2向大家說明如何聯合兩個委托。
例1
      這個例子說明如何聲明、實例化和使用委托。BookDB類壓縮了一個包含各種書籍的書店數據庫,它對外暴露PRocessPaperbackBooks方法,用以查找數據庫中所有平裝本的書籍并調用委托,使用委托來調用ProcessBookDelegate。Test類使用這個類來打印處平裝本書籍的標題和平均價格。
     委托的使用促進了書店數據庫與客戶端代碼之間功能性的良好分離??蛻舳舜a不用知曉書是如何存的如何找到平裝本,而書店的代碼不用知道查找到該平裝書并提供給客戶端后將會被如何處理。代碼如下(為了部影響理解,代碼保持原樣):


  1// bookstore.cs
  2using System;
  3// A set of classes for handling a bookstore:
  4namespace Bookstore
  5{
  6   using System.Collections;
  7   // Describes a book in the book list:
  8   public struct Book
  9   {
 10      public string Title;        // Title of the book.
 11      public string Author;       // Author of the book.
 12      public decimal Price;       // Price of the book.
 13      public bool Paperback;      // Is it paperback?
 14      public Book(string title, string author, decimal price, bool paperBack)
 15      {
 16         Title = title;
 17         Author = author;
 18         Price = price;
 19         Paperback = paperBack;
 20      }
 21   }
 22
 23   // Declare a delegate type for processing a book:
 24   public delegate void ProcessBookDelegate(Book book);
 25
 26   // Maintains a book database.
 27   public class BookDB
 28   {
 29      // List of all books in the database:
 30      ArrayList list = new ArrayList();  
 31
 32      // Add a book to the database:
 33      public void AddBook(string title, string author, decimal price, bool paperBack)
 34      {
 35         list.Add(new Book(title, author, price, paperBack));
 36      }
 37
 38      // Call a passed-in delegate on each paperback book to process it:
 39      public void ProcessPaperbackBooks(ProcessBookDelegate processBook)
 40      {
 41         foreach (Book b in list)
 42         {
 43            if (b.Paperback)
 44
 45            // Calling the delegate:
 46               processBook(b);
 47         }
 48      }
 49   }
 50}
 51// Using the Bookstore classes:
 52namespace BookTestClient
 53{
 54   using Bookstore;
 55
 56   // Class to total and average prices of books:
 57   class PriceTotaller
 58   {
 59      int countBooks = 0;
 60      decimal priceBooks = 0.0m;
 61      internal void AddBookToTotal(Book book)
 62      {
 63         countBooks += 1;
 64         priceBooks += book.Price;
 65      }
 66      internal decimal AveragePrice()
 67      {
 68         return priceBooks / countBooks;
 69      }
 70   }
 71   // Class to test the book database:
 72   class Test
 73   {
 74      // Print the title of the book.
 75      static void PrintTitle(Book b)
 76      {
 77         Console.WriteLine("   {0}", b.Title);
 78      }
 79      // Execution starts here.
 80      static void Main()
 81      {
 82         BookDB bookDB = new BookDB();
 83         // Initialize the database with some books:
 84         AddBooks(bookDB);     
 85         // Print all the titles of paperbacks:
 86         Console.WriteLine("Paperback Book Titles:");
 87         // Create a new delegate object associated with the static
 88         // method Test.PrintTitle:
 89         bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));
 90         // Get the average price of a paperback by using
 91         // a PriceTotaller object:
 92         PriceTotaller totaller = new PriceTotaller();
 93         // Create a new delegate object associated with the nonstatic
 94         // method AddBookToTotal on the object totaller:
 95         bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));
 96         Console.WriteLine("Average Paperback Book Price: ${0:#.##}",
 97            totaller.AveragePrice());
 98      }
 99      // Initialize the book database with some test books:
100      static void AddBooks(BookDB bookDB)
101      {
102         bookDB.AddBook("The C Programming Language",
103            "Brian W. Kernighan and Dennis M. Ritchie", 19.95m, true);
104         bookDB.AddBook("The Unicode Standard 2.0",
105            "The Unicode Consortium", 39.95m, true);
106         bookDB.AddBook("The MS-DOS Encyclopedia",
107            "Ray Duncan", 129.95m, false);
108         bookDB.AddBook("Dogbert's Clues for the Clueless",
109            "Scott Adams", 12.00m, true);
110      }
111   }
112}
113 
輸出:

    平裝書的標題:

   The C Programming Language
    The Unicode Standard 2.0

    Dogbert's Clues for the Clueless

平均價格: $23.97

討論:

委托的聲明

委托可聲明如下:
public delegate void ProcessBookDelegate(Book book);

聲明一個新的委托類型。每個委托類型可包含委托描述的數量和類型,包含被壓縮方法返回值的類型。不管是否需要一組類型描述或返回值類型,必須聲明一個新的委托類型。

 

實例化一個委托: 擋一個委托的類型被聲明后,必須創建委托對象并與一個特定的方法相關聯。和其他對象一樣,需要一起創建新的委托對象和新的表達式。

看看這段:
bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));

聲明一個關聯靜態方法Test.PrintTitle的委托對象。
再看看這段:
bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));

創建一個委托對象關聯totaller對象上的非靜態方法 AddBookToTotal。新的委托對象馬上被傳遞給ProcessPaperbackBooks方法。

請注意,委托一旦被創建后,其關聯的方法將不能再被更改,因為委托對象是不可變的。

 

調用委托:委托對象被創建后會被傳遞給調用委托的其他代碼。通過委托對象名稱和其后跟隨的括號化描述來調用委托對象,示例如下。

processBook(b);

如例中所示,委托可以被同步調用,也可以使用BeginInvoke和EndInvoke異步調用。

 

例2(示范如何聯合兩個委托)

這個例子示范了委托的構成,委托對象的一個有用屬性是他們可以使用”+”運算符來進行聯合,聯合委托調用組成它的兩個委托,只有類型相同的委托才可以聯合?!保辈僮鞣糜趶穆摵衔兄幸瞥粋€委托。示例代碼如下:
 

 1// compose.cs
 2using System;
 3delegate void MyDelegate(string s);
 4class MyClass
 5{
 6    public static void Hello(string s)
 7    {
 8        Console.WriteLine("  Hello, {0}!", s);
 9    }
10    public static void Goodbye(string s)
11    {
12        Console.WriteLine("  Goodbye, {0}!", s);
13    }
14    public static void Main()
15    {
16        MyDelegate a, b, c, d;
17        // Create the delegate object a that references
18        // the method Hello:
19        a = new MyDelegate(Hello);
20        // Create the delegate object b that references
21        // the method Goodbye:
22        b = new MyDelegate(Goodbye);
23        // The two delegates, a and b, are composed to form c:
24        c = a + b;
25        // Remove a from the composed delegate, leaving d,
26        // which calls only the method Goodbye:
27        d = c - a;
28        Console.WriteLine("Invoking delegate a:");
29        a("A");
30        Console.WriteLine("Invoking delegate b:");
31        b("B");
32        Console.WriteLine("Invoking delegate c:");
33        c("C");
34        Console.WriteLine("Invoking delegate d:");
35        d("D");
36    }
37}
38
 
輸出:

調用委托 a:
  Hello, A!
調用委托b:
  Goodbye, B!
調用委托c:
  Hello, C!
  Goodbye, C!
調用委托d:
  Goodbye, D!

委托與事件

      對于給組件的“聽眾”來通知該組件的發生的事件而言,使用委托特別適合。

委托 VS. 接口

    委托與接口在都能促成規范與執行的分離,有相似之處。那聲明時候使用委托聲明時候使用接口呢?大體依據以下原則:

如下情況宜使用委托:

只調用單個方法時.
當一個類需要方法說明的多重執行時.
期望使用靜態方法執行規范時.
期望得到一個類似事件的模式時.
調用者無需知道無需獲取定義方法的對象時
只想給少數既定組件分發執行規范時.
想要簡單的組成結構時.
如下情況宜使用接口:

當規范定義了一組需要調用的相關方法時.
一個類僅代表性地執行一次規范時.
接口的調用者想映射接口類型以獲取其他類或接口時


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久影视电视剧凤归四时歌| 久久精品国产亚洲精品2020| 亚洲第一福利视频| 国模gogo一区二区大胆私拍| 久久综合五月天| 欧美性高潮床叫视频| 理论片在线不卡免费观看| 日韩国产一区三区| 色噜噜狠狠狠综合曰曰曰| 永久免费毛片在线播放不卡| 亚洲精品之草原avav久久| 久久久999国产精品| 亚洲国产精品资源| 国产精品香蕉在线观看| 欧美性色xo影院| 国产成人精品一区二区三区| 久久免费成人精品视频| 国内精品视频一区| 成人免费福利在线| 国产精品成熟老女人| 亚洲精品久久久久久下一站| 国产日韩精品电影| 国产美女久久精品香蕉69| 国产精品女人久久久久久| 伊人伊成久久人综合网小说| 中文字幕av一区二区三区谷原希美| 国产91在线播放九色快色| 亚洲视频在线观看免费| 久久久久久久久久久91| 久久免费福利视频| 性色av一区二区三区在线观看| 九九久久国产精品| 中日韩美女免费视频网站在线观看| 亚洲精品国产美女| www.久久色.com| 日韩一区二区久久久| 国产精品小说在线| 国产999精品久久久影片官网| 欧美另类精品xxxx孕妇| 精品中文字幕视频| 精品国产网站地址| 国产欧美精品xxxx另类| 亚洲国产精品字幕| 欧美裸体视频网站| 国产乱肥老妇国产一区二| xxx成人少妇69| 国产精品美女www爽爽爽视频| 欧美精品成人在线| 91免费高清视频| 欧美华人在线视频| 欧美一区二区大胆人体摄影专业网站| 热99在线视频| 欧美床上激情在线观看| 中文字幕日韩有码| 51久久精品夜色国产麻豆| 国产高清视频一区三区| 亚洲精品网址在线观看| zzjj国产精品一区二区| 国产精品自拍视频| 91精品国产精品| 国产成人精品最新| 亚洲在线免费看| 欧美视频不卡中文| 九九热这里只有在线精品视| 91久久中文字幕| 免费91在线视频| 欧美黄色片视频| 97精品视频在线播放| 亚洲色图激情小说| 国产一区二区三区四区福利| 国产精品视频免费在线观看| 成人欧美一区二区三区在线湿哒哒| 欧美性视频网站| 自拍视频国产精品| 国产日韩欧美视频在线| 亚洲精品视频播放| 伊人久久久久久久久久久久久| 日韩精品在线视频观看| 欧美黑人国产人伦爽爽爽| 欧美洲成人男女午夜视频| 欧美电影免费观看大全| 精品国产乱码久久久久久虫虫漫画| 欧洲s码亚洲m码精品一区| 亚洲国产精品人人爽夜夜爽| 2019日本中文字幕| 久久精品成人动漫| 精品国产乱码久久久久久天美| 性欧美办公室18xxxxhd| 欧美亚洲成人精品| 久久中文字幕一区| 国产一区二区三区久久精品| 91黑丝高跟在线| 亚洲精品电影在线| 欧美精品久久久久久久久久| 欧美激情欧美狂野欧美精品| 国产成人精品免高潮在线观看| 欧美日韩国产一区中文午夜| 日韩亚洲成人av在线| 中文字幕在线观看日韩| 91色精品视频在线| 精品高清一区二区三区| 91精品国产免费久久久久久| 国产精品视频内| 日韩在线观看av| 日本精品免费观看| 欧美激情xxxx| 亚洲日本欧美日韩高观看| 色偷偷av一区二区三区乱| 中文.日本.精品| 日韩69视频在线观看| 亚洲精品视频网上网址在线观看| 国产精品免费久久久久影院| 国产做受高潮69| 91人成网站www| 国产亚洲欧美日韩一区二区| 国产精品678| 国产精品扒开腿爽爽爽视频| 国产在线精品一区免费香蕉| 亚洲欧美国产另类| 欧美日韩中文字幕在线| 久久精品视频在线播放| 日韩精品久久久久久久玫瑰园| 日韩中文字幕不卡视频| 亚洲电影免费观看高清| 97精品视频在线| 91精品国产91久久久久久不卡| 狠狠色香婷婷久久亚洲精品| 欧美亚洲国产日韩2020| 亚洲欧洲日产国码av系列天堂| 国内精品久久久久久中文字幕| 国产成人一区二区三区| 亚洲在线免费看| 久久国产精品亚洲| 久久频这里精品99香蕉| 日韩国产高清污视频在线观看| 91中文在线视频| 国产香蕉一区二区三区在线视频| 91久久精品国产91性色| 亚洲精品videossex少妇| 亚洲成**性毛茸茸| 欧美性猛交视频| 成人免费激情视频| 中文字幕日韩精品有码视频| 亚洲精品一区二区三区不| 亚洲精品久久久一区二区三区| 日韩欧美在线视频| www.久久色.com| 欧美一性一乱一交一视频| 久久精品视频亚洲| 俺也去精品视频在线观看| 国产精品福利网站| 亚洲国产一区二区三区四区| 91大神福利视频在线| 55夜色66夜色国产精品视频| 国产91精品在线播放| 欧美精品在线免费播放| 北条麻妃在线一区二区| 91精品国产自产91精品| 欧美高清一级大片| 久久久精品久久久| 亚洲丝袜一区在线| 亚洲精品成人久久电影| 亚洲人成免费电影| 欧美激情videoshd|