關於.NET的委託

 .NET學習中,你碰到過委託嗎?我接觸.NET幾個月以來,關於委託的確花了我好長時間才弄明白,這裏我就C#中的委託給大家介紹一下。(先說定義和特徵,然後用例子說明)

    委託是回調函數的類型安全包裝。C++編寫的非託管程序進行回調時很容易出錯。由於委託的存在,託管應用程序不會出現這樣的情況。委託通常用來定義響應事件的回調方法的簽名。

    C#中的委託類似於C或C++中的函數指針。使用委託使程序員可以將方法引用封裝在委託對象內( 所以這裏的“引用”不是原始內存地址,而是包裝了方法的內存地址的委託實例 )。然後可以將給委託對象傳遞可調用所引用方法的代碼,而不必在編譯時知道將調用哪個方法。與C或C++中的函數指針不同,委託是面向對象、類型安全的,並且是安全的。

    委託聲明定義一種類型,它用一組特定的參數以及返回類型封裝方法。

    對於靜態方法,委託對象封裝要調用的方法。

    對於實例方法,委託對象同時封裝一個實例和該實例上的一個方法。

    如果你有一個委託對象和一組適當的參數,則可以用這些參數調用該委託。

    委託的一個有趣且有用的屬性是: 它不知道或不關心自己引用的對象的類。任何對象都可以,知識方法的參數類型必須與委託的參數類型和返回類型相匹配。這是的委託完全適合“匿名”調用。

    到現在已經說得不少了,現在開始用例子說明如何聲明、實例化和調用委託:下面的示例中,BookDB 類封裝一個書店數據庫,它維護一個書籍數據庫。它公開 ProcessPaperbackBooks 方法,該方法在數據庫中查找所有平裝書,併爲每本書調用一個委託。所使用的 delegate 類型稱爲 ProcessBookDelegate.Test 類使用該類輸出平裝書的書名和平均價格。委託的使用促進了書店數據庫和客戶代碼之間功能的良好分隔。客戶代碼不知道書籍的存儲方式和書店代碼查找平裝書的方式。書店代碼也不知道找到平裝書後將對平裝書進行什麼處理。

詳細介紹有關於.NET的委託(圖一)// bookstore.cs
詳細介紹有關於.NET的委託(圖一)using System;
詳細介紹有關於.NET的委託(圖一)
詳細介紹有關於.NET的委託(圖一)//此命名空間中的幾個類用以維護書籍數據庫:
詳細介紹有關於.NET的委託(圖一)namespace Bookstore 
詳細介紹有關於.NET的委託(圖二)詳細介紹有關於.NET的委託(圖三)...{
詳細介紹有關於.NET的委託(圖四)   using System.Collections;
詳細介紹有關於.NET的委託(圖四)
詳細介紹有關於.NET的委託(圖四)   // 描述數據庫中每一本書具有的屬性:
詳細介紹有關於.NET的委託(圖四)   public struct Book
詳細介紹有關於.NET的委託(圖五)詳細介紹有關於.NET的委託(圖六)   ...{
詳細介紹有關於.NET的委託(圖四)      public string Title;        // 書的題目.
詳細介紹有關於.NET的委託(圖四)      public string Author;       // 書的作者.
詳細介紹有關於.NET的委託(圖四)      public decimal Price;       // 書的價格.
詳細介紹有關於.NET的委託(圖四)      public bool Paperback;      // 是不是平裝書?
詳細介紹有關於.NET的委託(圖四)
詳細介紹有關於.NET的委託(圖四)      public Book(string title, string author, decimal price, bool paperBack)
詳細介紹有關於.NET的委託(圖五)詳細介紹有關於.NET的委託(圖六)      ...{
詳細介紹有關於.NET的委託(圖四)         Title = title;
詳細介紹有關於.NET的委託(圖四)         Author = author;
詳細介紹有關於.NET的委託(圖四)         Price = price;
詳細介紹有關於.NET的委託(圖四)         Paperback = paperBack;
詳細介紹有關於.NET的委託(圖七)      }
詳細介紹有關於.NET的委託(圖七)   }
詳細介紹有關於.NET的委託(圖四)
詳細介紹有關於.NET的委託(圖四)   // 爲處理平裝書的類聲明一個委託類型(delegate類型):
詳細介紹有關於.NET的委託(圖四)   public delegate void ProcessBookDelegate(Book book);
詳細介紹有關於.NET的委託(圖四)
詳細介紹有關於.NET的委託(圖四)   // 維護書籍的數據庫.
詳細介紹有關於.NET的委託(圖四)   public class BookDB
詳細介紹有關於.NET的委託(圖五)詳細介紹有關於.NET的委託(圖六)   ...{
詳細介紹有關於.NET的委託(圖四)      // 數據庫中所有書籍的清單:
詳細介紹有關於.NET的委託(圖四)      ArrayList list = new ArrayList();   
詳細介紹有關於.NET的委託(圖四)
詳細介紹有關於.NET的委託(圖四)      // 向數據庫中添加一本書:
詳細介紹有關於.NET的委託(圖四)      public void AddBook(string title, string author, decimal price, bool paperBack)
詳細介紹有關於.NET的委託(圖五)詳細介紹有關於.NET的委託(圖六)      ...{
詳細介紹有關於.NET的委託(圖四)         list.Add(new Book(title, author, price, paperBack));
詳細介紹有關於.NET的委託(圖七)      }
詳細介紹有關於.NET的委託(圖四)
詳細介紹有關於.NET的委託(圖四)      // 對於每一本平裝書調用ProcessBookDelegate這個委託,以對平裝書進行處理: 
詳細介紹有關於.NET的委託(圖四)      public void ProcessPaperbackBooks(ProcessBookDelegate processBook)
詳細介紹有關於.NET的委託(圖五)詳細介紹有關於.NET的委託(圖六)      ...{
詳細介紹有關於.NET的委託(圖四)         foreach (Book b in list) 
詳細介紹有關於.NET的委託(圖五)詳細介紹有關於.NET的委託(圖六)         ...{
詳細介紹有關於.NET的委託(圖四)            if (b.Paperback)
詳細介紹有關於.NET的委託(圖四)            // Calling the delegate:
詳細介紹有關於.NET的委託(圖四)               processBook(b);
詳細介紹有關於.NET的委託(圖七)         }
詳細介紹有關於.NET的委託(圖七)      }
詳細介紹有關於.NET的委託(圖七)   }
詳細介紹有關於.NET的委託(圖八)}
詳細介紹有關於.NET的委託(圖一)
詳細介紹有關於.NET的委託(圖一)// 使用Bookstore命名空間裏的類:
詳細介紹有關於.NET的委託(圖一)namespace BookTestClient
詳細介紹有關於.NET的委託(圖二)詳細介紹有關於.NET的委託(圖三)...{
詳細介紹有關於.NET的委託(圖四)   using Bookstore;
詳細介紹有關於.NET的委託(圖四)
詳細介紹有關於.NET的委託(圖四)   // 具有統計平裝書並求出平裝書的平均價格功能的類:
詳細介紹有關於.NET的委託(圖四)   class PriceTotaller
詳細介紹有關於.NET的委託(圖五)詳細介紹有關於.NET的委託(圖六)   ...{
詳細介紹有關於.NET的委託(圖四)      int countBooks = 0;
詳細介紹有關於.NET的委託(圖四)      decimal priceBooks = 0.0m;
詳細介紹有關於.NET的委託(圖四)
詳細介紹有關於.NET的委託(圖四)      internal void AddBookToTotal(Book book)
詳細介紹有關於.NET的委託(圖五)詳細介紹有關於.NET的委託(圖六)      ...{
詳細介紹有關於.NET的委託(圖四)         countBooks += 1;
詳細介紹有關於.NET的委託(圖四)         priceBooks += book.Price;
詳細介紹有關於.NET的委託(圖七)      }
詳細介紹有關於.NET的委託(圖四)
詳細介紹有關於.NET的委託(圖四)      internal decimal AveragePrice()
詳細介紹有關於.NET的委託(圖五)詳細介紹有關於.NET的委託(圖六)      ...{
詳細介紹有關於.NET的委託(圖四)         return priceBooks / countBooks;
詳細介紹有關於.NET的委託(圖七)      }
詳細介紹有關於.NET的委託(圖七)   }
詳細介紹有關於.NET的委託(圖四)
詳細介紹有關於.NET的委託(圖四)   // 用以測試書籍數據庫的類:
詳細介紹有關於.NET的委託(圖四)   class Test
詳細介紹有關於.NET的委託(圖五)詳細介紹有關於.NET的委託(圖六)   ...{
詳細介紹有關於.NET的委託(圖四)      // 打印書籍題目的靜態方法.
詳細介紹有關於.NET的委託(圖四)      static void PrintTitle(Book b)
詳細介紹有關於.NET的委託(圖五)詳細介紹有關於.NET的委託(圖六)      ...{
詳細介紹有關於.NET的委託(圖四)         Console.WriteLine("   {0}", b.Title);
詳細介紹有關於.NET的委託(圖七)      }
詳細介紹有關於.NET的委託(圖四)
詳細介紹有關於.NET的委託(圖四)      // 程序執行的入口:
詳細介紹有關於.NET的委託(圖四)      static void Main()
詳細介紹有關於.NET的委託(圖五)詳細介紹有關於.NET的委託(圖六)      ...{
詳細介紹有關於.NET的委託(圖四)         BookDB bookDB = new BookDB();
詳細介紹有關於.NET的委託(圖四)
詳細介紹有關於.NET的委託(圖四)         // 用幾本書來輸初始化書籍數據庫:
詳細介紹有關於.NET的委託(圖四)         AddBooks(bookDB);      
詳細介紹有關於.NET的委託(圖四)
詳細介紹有關於.NET的委託(圖四)         // 打印平裝書的題目:
詳細介紹有關於.NET的委託(圖四)         Console.WriteLine("Paperback Book Titles:");
詳細介紹有關於.NET的委託(圖四)           // 創建與靜態方法 Test.PrintTitle 關聯的新的委託對象:
詳細介紹有關於.NET的委託(圖四)           bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));
詳細介紹有關於.NET的委託(圖四)
詳細介紹有關於.NET的委託(圖四)         // 通過PriceTotaller的實例獲取平裝書的平均價格:
詳細介紹有關於.NET的委託(圖四)         PriceTotaller totaller = new PriceTotaller();
詳細介紹有關於.NET的委託(圖四)           // 創建與對象 totaller 上的非靜態方法 AddBookToTotal 關聯的新的委託對象:
詳細介紹有關於.NET的委託(圖四)           bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));
詳細介紹有關於.NET的委託(圖四)         Console.WriteLine("平裝書的平均價格: ${0:#.##}",
詳細介紹有關於.NET的委託(圖四)            totaller.AveragePrice());
詳細介紹有關於.NET的委託(圖七)      }
詳細介紹有關於.NET的委託(圖四)
詳細介紹有關於.NET的委託(圖四)      // 向數據庫添加書以初始化書籍數據庫:
詳細介紹有關於.NET的委託(圖四)      static void AddBooks(BookDB bookDB)
詳細介紹有關於.NET的委託(圖五)詳細介紹有關於.NET的委託(圖六)      ...{
詳細介紹有關於.NET的委託(圖四)         bookDB.AddBook("The C Programming Language", 
詳細介紹有關於.NET的委託(圖四)            "Brian W. Kernighan and Dennis M. Ritchie", 19.95m, true);
詳細介紹有關於.NET的委託(圖四)         bookDB.AddBook("The Unicode Standard 2.0", 
詳細介紹有關於.NET的委託(圖四)            "The Unicode Consortium", 39.95m, true);
詳細介紹有關於.NET的委託(圖四)         bookDB.AddBook("The MS-DOS Encyclopedia", 
詳細介紹有關於.NET的委託(圖四)            "Ray Duncan", 129.95m, false);
詳細介紹有關於.NET的委託(圖四)         bookDB.AddBook("Dogbert's Clues for the Clueless", 
詳細介紹有關於.NET的委託(圖四)            "Scott Adams", 12.00m, true);
詳細介紹有關於.NET的委託(圖七)      }
詳細介紹有關於.NET的委託(圖七)   }
詳細介紹有關於.NET的委託(圖八)}
詳細介紹有關於.NET的委託(圖一)
詳細介紹有關於.NET的委託(圖一)輸出:
詳細介紹有關於.NET的委託(圖一)Paperback Book Titles:
詳細介紹有關於.NET的委託(圖一)   The C Programming Language
詳細介紹有關於.NET的委託(圖一)   The Unicode Standard 2.0
詳細介紹有關於.NET的委託(圖一)   Dogbert's Clues for the Clueless
詳細介紹有關於.NET的委託(圖一)平裝書的平均價格: $23.97
聲明委託   以下語句:   

public delegate void ProcessBookDelegate(Book book); 

     聲明一個新的委託類型。每個委託類型都描述參數的數目和類型,以及它可以封裝的方法的返回值類型。每當需要一組新的參數類型或新的返回值類型時,都必須聲明一個新的委託類型。

    實例化委託   聲明瞭委託類型後,必須創建委託對象並使之與特定方法關聯。與所有其他對象類似,新的委託對象用 new 表達式創建。但是當創建委託時,傳遞給 new 表達式的參數很特殊:它的編寫類似於方法調用,但沒有方法的參數。下列語句:

 bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));

     創建與靜態方法 Test.PrintTitle 關聯的新的委託對象。下列語句:

bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));

      創建與對象 totaller 上的非靜態方法 AddBookToTotal 關聯的新的委託對象。在例子中,新的委託對象都立即傳遞給 ProcessPaperbackBooks 方法。

    請注意一旦創建了委託,它所關聯到的方法便永不改變:委託對象不可改變。

    調用委託   創建委託對象後,通常將委託對象傳遞給將調用該委託的其他代碼。通過委託對象的名稱(後面跟着要傳遞給委託的參數,括在括號內)調用委託對象。下面是委託調用的示例:

 processBook(b);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章