熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

asp.net教程-委托(Delegate)

2022-06-13   來源: .NET編程 
    C# 中的委托類似於 C 或 C++ 中的函數指針使用委托使程序員可以將方法引用封裝在委托對象內然後可以將該委托對象傳遞給可調用所引用方法的代碼而不必在編譯時知道將調用哪個方法與 C 或 C++ 中的函數指針不同委托是面向對象類型安全的並且是安全的
   
    委托聲明定義一種類型它用一組特定的參數以及返回類型封裝方法對於靜態方法委托對象封裝要調用的方法對於實例方法委托對象同時封裝一個實例和該實例上的一個方法如果您有一個委托對象和一組適當的參數則可以用這些參數調用該委托
   
    委托的一個有趣且有用的屬性是它不知道或不關心自己引用的對象的類任何對象都可以只是方法的參數類型和返回類型必須與委托的參數類型和返回類型相匹配這使得委托完全適合匿名調用
   
    此源碼下載>教程包括兩個示例
   
    示例 展示如何聲明實例化和調用委托
   
    示例 展示如何組合兩個委托
   
    此外還討論以下主題
   
    委托和事件
   
    委托與接口
   
    示例
   
    下面的示例闡釋聲明實例化和使用委托BookDB 類封裝一個書店數據庫它維護一個書籍數據庫它公開 ProcessPaperbackBooks 方法該方法在數據庫中查找所有平裝書並為每本書調用一個委托所使用的 delegate 類型稱為 ProcessBookDelegateTest 類使用該類輸出平裝書的書名和平均價格
   
    委托的使用促進了書店數據庫和客戶代碼之間功能的良好分隔客戶代碼不知道書籍的存儲方式和書店代碼查找平裝書的方式書店代碼也不知道找到平裝書後將對平裝書進行什麼處理
   
    // bookstorecs
   
    using System;
   
    // A set of classes for handling a bookstore:
   
    namespace Bookstore
   
    {
   
    using SystemCollections;
   
    // Describes a book in the book list:
   
    public struct Book
   
    {
   
    public string Title; // Title of the book
   
    public string Author; // Author of the book
   
    public decimal Price; // Price of the book
   
    public bool Paperback; // Is it paperback?
   
    public Book(string title string author decimal price bool paperBack)
   
    {
   
    Title = title;
   
    Author = author;
   
    Price = price;
   
    Paperback = paperBack;
   
    }
   
    }


   
    // Declare a delegate type for processing a book:
   
    public delegate void ProcessBookDelegate(Book book)
   
    // Maintains a book database
   
    public class BookDB
   
    {
   
    // List of all books in the database:
   
    ArrayList list = new ArrayList()
   
    // Add a book to the database:
   
    public void AddBook(string title string author decimal price bool paperBack)
   
    {
   
    listAdd(new Book(title author price paperBack))
   
    }
   
    // Call a passedin delegate on each paperback book to process it:
   
    public void ProcessPaperbackBooks(ProcessBookDelegate processBook)
   
    {
   
    foreach (Book b in list)
   
    {
   
    if (bPaperback)
   
    // Calling the delegate:
   
    processBook(b)
   
    }
   
    }
   
    }
   
    }
   
    // Using the Bookstore classes:
   
    namespace BookTestClient
   
    {
   
    using Bookstore;
   
    // Class to total and average prices of books:
   
    class PriceTotaller
   
    {
   
    int countBooks = ;
   
    decimal priceBooks = m;
   
    internal void AddBookToTotal(Book book)
   
    {
   
    countBooks += ;
   
    priceBooks += bookPrice;
   
    }
   
    internal decimal AveragePrice()
   
    {
   
    return priceBooks / countBooks;
   
    }
   
    }
   
    // Class to test the book database:
   
    class Test
   
    {
   
    // Print the title of the book
   
    static void PrintTitle(Book b)
   
    {
   
    ConsoleWriteLine( {} bTitle)
   
    }
   
    // Execution starts here
   
    static void Main()
   
    {
   
    BookDB bookDB = new BookDB()
   
    // Initialize the database with some books:
   
    AddBooks(bookDB)
   
    // Print all the titles of paperbacks:
   
    ConsoleWriteLine(Paperback Book Titles:
   
    // Create a new delegate object associated with the static
   
    // method TestPrintTitle:
   
    bookDBProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle))
   
    // Get the average price of a paperback by using
   
    // a PriceTotaller object:
   
    PriceTotaller totaller = new PriceTotaller()
   
    // Create a new delegate object associated with the nonstatic
   
    // method AddBookToTotal on the object totaller:
   
    bookDBProcessPaperbackBooks(new ProcessBookDelegate(totallerAddBookToTotal))
   
    ConsoleWriteLine(Average Paperback Book Price: ${:###}
   
    totallerAveragePrice())
   
    }
   
    // Initialize the book database with some test books:
   
    static void AddBooks(BookDB bookDB)
   
    {
   
    bookDBAddBook(The C Programming Language
   
    Brian W Kernighan and Dennis M Ritchie m true)
   
    bookDBAddBook(The Unicode Standard
   
    The Unicode Consortium m true)
   
    bookDBAddBook(The MSDOS Encyclopedia
   
    Ray Duncan m false)
   
    bookDBAddBook(Dogberts Clues for the Clueless
   
    Scott Adams m true)
   
    }
   
    }
   
    }
   


    輸出
   
    Paperback Book Titles:
   
    The C Programming Language
   
    The Unicode Standard
   
    Dogberts Clues for the Clueless
   
    Average Paperback Book Price: $
   
    代碼討論
   
    聲明委托 以下語句
   
    public delegate void ProcessBookDelegate(Book book)
   
    聲明一個新的委托類型每個委托類型都描述參數的數目和類型以及它可以封裝的方法的返回值類型每當需要一組新的參數類型或新的返回值類型時都必須聲明一個新的委托類型
   
    實例化委托 聲明了委托類型後必須創建委托對象並使之與特定方法關聯與所有其他對象類似新的委托對象用 new 表達式創建但創建委托時傳遞給 new 表達式的參數很特殊它的編寫類似於方法調用但沒有方法的參數
   
    下列語句
   
    bookDBProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle))
   
    創建與靜態方法 TestPrintTitle 關聯的新的委托對象下列語句
   
    bookDBProcessPaperbackBooks(new
   
    ProcessBookDelegate(totallerAddBookToTotal))
   
    創建與對象 totaller 上的非靜態方法 AddBookToTotal 關聯的新的委托對象在兩個例子中新的委托對象都立即傳遞給 ProcessPaperbackBooks 方法
   
    請注意一旦創建了委托它所關聯到的方法便永不改變委托對象不可改變
   
    調用委托 創建委托對象後通常將委托對象傳遞給將調用該委托的其他代碼通過委托對象的名稱(後面跟著要傳遞給委托的參數括在括號內)調用委托對象下面是委托調用的示例
   
    processBook(b)
   


    示例
   
    本示例演示組合委托委托對象的一個有用屬性是它們可以+運算符來組合組合的委托依次調用組成它的兩個委托只可組合相同類型的委托並且委托類型必須具有 void 返回值運算符可用來從組合的委托移除組件委托
   
    // composecs
   
    using System;
   
    delegate void MyDelegate(string s)
   
    class MyClass
   
    {
   
    public static void Hello(string s)
   
    {
   
    ConsoleWriteLine( Hello {}! s)
   
    }
   
    public static void Goodbye(string s)
   
    {
   
    ConsoleWriteLine( Goodbye {}! s)
   
    }
   
    public static void Main()
   
    {
   
    MyDelegate a b c d;
   
    // Create the delegate object a that references
   
    // the method Hello:
   
    a = new MyDelegate(Hello)
   
    // Create the delegate object b that references
   
    // the method Goodbye:
   
    b = new MyDelegate(Goodbye)
   
    // The two delegates a and b are composed to form c
   
    // which calls both methods in order:
   
    c = a + b;
   
    // Remove a from the composed delegate leaving d
   
    // which calls only the method Goodbye:
   
    d = c a;
   
    ConsoleWriteLine(Invoking delegate a:
   
    a(A
   
    ConsoleWriteLine(Invoking delegate b:
   
    b(B
   
    ConsoleWriteLine(Invoking delegate c:
   
    c(C
   
    ConsoleWriteLine(Invoking delegate d:
   
    d(D
   
    }
   
    }
   
    輸出
   
    Invoking delegate a:
   
    Hello A!
   
    Invoking delegate b:
   
    Goodbye B!
   
    Invoking delegate c:
   
    Hello C!
   
    Goodbye C!
   
    Invoking delegate d:
   
    Goodbye D!
   
    委托和事件
   
    委托非常適合於用作事件(從一個組件就該組件中的更改通知偵聽器
   
    委托與接口
   
    委托和接口的類似之處是它們都允許分隔規范和實現多個獨立的作者可以生成與一個接口規范兼容的多個實現類似地委托指定方法的簽名多個作者可以編寫與委托規范兼容的多個方法何時應使用接口而何時應使用委托呢?
   
    委托在以下情況下很有用
   
    調用單個方法
   
    一個類可能希望有方法規范的多個實現
   
    希望允許使用靜態方法實現規范
   
    希望類似事件的設計模式
   
    調用方不需要知道或獲得在其上定義方法的對象
   
    實現的提供程序希望只對少數選擇組件分發規范實現
   
    需要方便的組合
   
    接口在以下情況下很有用
   
    規范定義將調用的一組相關方法
   
    類通常只實現規范一次
   
    接口的調用方希望轉換為接口類型或從接口類型轉換以獲得其他接口或類


From:http://tw.wingwit.com/Article/program/net/201311/12347.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.