<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    302班

    java突擊隊
    posts - 151, comments - 74, trackbacks - 0, articles - 14
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    c#中的委托

    Posted on 2007-06-15 20:02 停留的風 閱讀(138) 評論(0)  編輯  收藏

      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. 接口

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

    如下情況宜使用委托:

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

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


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 国产性爱在线观看亚洲黄色一级片| 国产成人综合久久精品亚洲| 亚洲国产精品视频| 曰曰鲁夜夜免费播放视频| 国产乱子伦精品免费视频| 亚洲精品无码久久| 亚洲日韩在线视频| 久久精品亚洲一区二区三区浴池 | 国产免费人成视频在线观看| 69国产精品视频免费| 在线观看免费视频一区| 免费精品国产自产拍在线观看| 国产成人精品日本亚洲11| 亚洲伦另类中文字幕| 亚洲乱码中文字幕久久孕妇黑人| 免费**毛片在线播放直播 | 亚洲一区二区免费视频| 亚洲va无码va在线va天堂| 亚洲色无码一区二区三区| 亚洲国产精品一区二区九九 | 亚洲精品中文字幕无乱码| 亚洲成色www久久网站夜月| 综合久久久久久中文字幕亚洲国产国产综合一区首 | 亚洲一级毛片免费看| 免费一级毛片在线播放视频| 国产精品1024在线永久免费 | 亚洲精品无码久久久| 无码欧精品亚洲日韩一区夜夜嗨| 日本免费观看网站| 狠狠久久永久免费观看| 在线观看免费毛片| 午夜a级成人免费毛片| 爽爽日本在线视频免费| 国产精品免费_区二区三区观看| 免费高清在线爱做视频| 大陆一级毛片免费视频观看| 在线观看免费a∨网站| 国内自产少妇自拍区免费| 精品国产免费一区二区| 精品剧情v国产在免费线观看| 卡1卡2卡3卡4卡5免费视频|