<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 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

    c#中的委托

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

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

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

     

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

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

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

    創(chuàng)建一個委托對象關聯(lián)totaller對象上的非靜態(tài)方法 AddBookToTotal。新的委托對象馬上被傳遞給ProcessPaperbackBooks方法。

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

     

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

    processBook(b);

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

     

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

    這個例子示范了委托的構成,委托對象的一個有用屬性是他們可以使用”+”運算符來進行聯(lián)合,聯(lián)合委托調用組成它的兩個委托,只有類型相同的委托才可以聯(lián)合。”-”操作符用于從聯(lián)合委托中移除一個委托。示例代碼如下:
     

     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!

    委托與事件

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

    委托 VS. 接口

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

    如下情況宜使用委托:

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

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


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


    網(wǎng)站導航:
     
    主站蜘蛛池模板: 国内精品99亚洲免费高清| 成人免费的性色视频| 国产片免费在线观看| 亚洲人成网亚洲欧洲无码| 在线精品免费视频| 亚洲日韩国产二区无码 | 国产亚洲美女精品久久久久狼| 色多多www视频在线观看免费| 国产男女猛烈无遮档免费视频网站 | 在线观看亚洲成人| GOGOGO高清免费看韩国| 亚洲愉拍99热成人精品热久久| 中文字幕在线免费播放| 国产精品亚洲аv无码播放| 久久香蕉国产线看免费| 久久精品国产亚洲AV无码偷窥| 99久久久精品免费观看国产| 亚洲一区无码中文字幕乱码| 成年女人毛片免费播放视频m| 亚洲av成人无码网站…| 亚洲乱亚洲乱少妇无码| 日韩视频在线观看免费| 亚洲精品在线免费看| 免费看大黄高清网站视频在线| 精品在线观看免费| 亚洲av综合色区| 免费专区丝袜脚调教视频| 亚洲中文字幕无码亚洲成A人片| 国产一级淫片a视频免费观看| 久久久WWW免费人成精品| 亚洲avav天堂av在线不卡| 无码乱肉视频免费大全合集 | 国产精品亚洲自在线播放页码| 国产男女猛烈无遮挡免费视频网站 | 亚洲AV无码一区二区三区DV| 精品久久久久久久久免费影院| 国产精品久久亚洲一区二区| 亚洲av无码专区国产乱码在线观看| 在线观看免费高清视频| 一区二区三区免费视频观看| 亚洲精品乱码久久久久久下载|