关于.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);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值