码迷,mamicode.com
首页 > 其他好文 > 详细

C# 委托

时间:2014-05-28 01:29:07      阅读:296      评论:0      收藏:0      [点我收藏+]

标签:des   c   class   code   tar   http   

委托


这篇教程论述了委托类型,它显示了如何委托映射到静态方法和实例方法,以及如何将他们相结合(多播)。

 

延伸阅读

教程

C#中的委托类似于C或C++中的函数指针,使用委托允许开发者将一个函数引用封装进一个委托对象,然后,委托对象可以作为参数传到需要调用这个函数的代码块中,编译时不需要知道哪个函数会被调用。和C或C++的区别在于,委托是面向对象、类型安全和过程安全的。

 

委托声明定义了一种将函数的参数和返回值封装的类型。对于静态方法,委托将方法封装以便于被调用。对于实例方法,委托将实例和方法一起封装进这个委托实例。如果你知道一个委托的实例和适当的参数,你就可以通过参数调用这个委托。

 

委托有一个既有趣有比较有用的特性是,他不知道或者不关心引用对象的类型,任何对象都会执行一样的操作,重要的是函数的参数类型和返回值是否和委托匹配。这让委托非常适合“匿名”调用。

:委托在调用处而不是声明处的安全许可下运行。

 

本教程有两个例子:

  • 实例1 演示如何声明、初始化和调用一个委托
  • 实例2 演示如何结合两个委托

除此之外,还讨论了下面两个话题:

  • 委托和事件
  • 委托与接口

实例1


下面的例子阐明声明、实例化和如何使用一个委托。BookDB类封装了书店数据库中的书籍数据,它暴露了一个方法ProcessPaperbakcBooks,找到所有书籍数据然后为每个数据调用一个委托,委托的名字是ProcessBookDelegate。Test类使用这个类打印每本平装书的书名和计算平均价格。

 

委托的作用就是提升书店数据库和客户端代码的功能的良好分隔(耦合度)。客户端代码不知道书籍信息是如何存储也不知道bookstore中的代码是如何找到所有平装书的,bookesotre也不知道当他找到所有平装书后会执行什么流程。

 

--------------------------------------------------------------------------------------------------------------------

// bookstore.cs
using System;

// A set of classes for handling a bookstore:
namespace Bookstore 
{
   using System.Collections;

   // 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)
      {
         list.Add(new Book(title, author, price, paperBack));
      }

      // Call a passed-in delegate on each paperback book to process it: 
      public void ProcessPaperbackBooks(ProcessBookDelegate processBook)
      {
         foreach (Book b in list) 
         {
            if (b.Paperback)
            // 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 = 0;
      decimal priceBooks = 0.0m;

      internal void AddBookToTotal(Book book)
      {
         countBooks += 1;
         priceBooks += book.Price;
      }

      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)
      {
         Console.WriteLine("   {0}", b.Title);
      }

      // Execution starts here.
      static void Main()
      {
         BookDB bookDB = new BookDB();

         // Initialize the database with some books:
         AddBooks(bookDB);      

         // Print all the titles of paperbacks:
         Console.WriteLine("Paperback Book Titles:");
         // Create a new delegate object associated with the static 
         // method Test.PrintTitle:
         bookDB.ProcessPaperbackBooks(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:
         bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));
         Console.WriteLine("Average Paperback Book Price: ${0:#.##}",
            totaller.AveragePrice());
      }

      // Initialize the book database with some test books:
      static void AddBooks(BookDB bookDB)
      {
         bookDB.AddBook("The C Programming Language", 
            "Brian W. Kernighan and Dennis M. Ritchie", 19.95m, true);
         bookDB.AddBook("The Unicode Standard 2.0", 
            "The Unicode Consortium", 39.95m, true);
         bookDB.AddBook("The MS-DOS Encyclopedia", 
            "Ray Duncan", 129.95m, false);
         bookDB.AddBook("Dogbert‘s Clues for the Clueless", 
            "Scott Adams", 12.00m, true);
      }
   }
}

--------------------------------------------------------------------------------------------------------------------

输出

Paperback Book Titles:
   The C Programming Language
   The Unicode Standard 2.0
   Dogbert‘s Clues for the Clueless
Average Paperback Book Price: $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。这两种情况下,委托对象都会立即传送至ProcessPaperbakcBooks方法。

  

  注意,一旦创建了一个委托,它所指定的函数标签就不能改变-委托对象是不可变的。

 

  • 调用委托   一旦创建了一个累托类型,委托对象就会以它的工作方式传送给其他代码调用委托。委托对象使用委托对象名来调用,并且后面需要带参数表。例如:    
    processBook(b);

  委托既能同步调用就想本例中一样,也能异步调用,异步调用使用 BeginInvoke  EndInvoke 方法。

C# 委托,布布扣,bubuko.com

C# 委托

标签:des   c   class   code   tar   http   

原文地址:http://www.cnblogs.com/fly-100/p/3753771.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!