delegate委托

delegate委托:
三个概念:
C# 中的委托类似于 C 或 C++ 中的函数指针。
委托是面向对象、类型安全的,并且是安全的。
委托和接口的类似之处是:它们都允许分隔规范和实现。
一个原则:
被托管函数的返回和参数必须和声明的托管相同;

基于这三个概念来看这个例子,这是微软的教程上讲的一个例子:

示例阐释声明、实例化和使用委托。BookDB 类封装一个书店数据库,它维护一个书籍数据库。它公开 ProcessPaperbackBooks 方法,该方法在数据库中查找所有平装书,并为每本书调用一个委托。所使用的 delegate 类型称为 ProcessBookDelegate。Test 类使用该类输出平装书的书名和平均价格。

委托的使用促进了书店数据库和客户代码之间功能的良好分隔。客户代码不知道书籍的存储方式和书店代码查找平装书的方式。书店代码也不知道找到平装书后将对平装书进行什么处理。

using System;
namespace Bookstore
{
   using System.Collections;
//1 声明Book
   public struct Book
   {
      public string Title;        // 书名
      public string Author;       // 作者
      public decimal Price;       // 价格
      public bool Paperback;      // 简装
 //构造函数
      public Book(string title, string author, decimal price, bool paperBack)
      {
         Title = title;
         Author = author;
         Price = price;
         Paperback = paperBack;
      }
   }
   //2 托管声明:注意参数是Book,返回值void
   public delegate void ProcessBookDelegate(Book book);
  //3 书库
   public class BookDB
   {
      ArrayList list = new ArrayList();  
      public void AddBook(string title, string author, decimal price, bool paperBack)
      {
         list.Add(new Book(title, author, price, paperBack));
      }
      public void ProcessPaperbackBooks(ProcessBookDelegate processBook)
      {
         foreach (Book b in list)
         {
            if (b.Paperback)
           //12.processBook,他的调用和在运行是调用的就是PrintTitle()
               processBook(b);
         }
      }
   }
}

// 4 使用端
namespace BookTestClient
{
   using Bookstore;

   // Class to total and average prices of books:
   class PriceTotaller
   {
      int countBooks = 0;
      decimal priceBooks = 0.0m;
 //internal 修饰符使类、接口或成员仅在当前包中可见。     
        //当前包之外的代码不能访问 internal 成员。
       //在全局范围内,internal 修饰符与 public 修饰符相同
      internal void AddBookToTotal(Book book)
      {
         countBooks += 1;
         priceBooks += book.Price;
      }

      internal decimal AveragePrice()
      {
         return priceBooks / countBooks;
      }
   }

   //5.测试
   class Test
   {
      // 打印书名
      static void PrintTitle(Book b)
      {
         Console.WriteLine("   {0}", b.Title);
      }

      // 6 开始
      static void Main()
      {
 //构造书库,这不必细说,从BookDB可以看很明白
         BookDB bookDB = new BookDB();

        // 7初始化书库,函数在往下找8
         AddBooks(bookDB);     

        // 10 打印所有平装书
         Console.WriteLine("Paperback Book Titles:");
         // 11.关键点到了,新建了一个托管对象,参数是Test.PrintTitle
         // 什么意思呢?先看PrintTitle(),他的参数和返回值和声明的托管
 //要求的一致,我得理解是把这个函数的引用或者函数指针封装之后,当作参数
 //交给函数ProcessPaperbackBooks  向上到12
         bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));

  //13 同样的函数只要和委托在返回和参数上相同,就可以用了!
         PriceTotaller totaller = new PriceTotaller();

         bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));
         Console.WriteLine("Average Paperback Book Price: ${0:#.##}",
            totaller.AveragePrice());
      }

      // 8 把书存到里面
      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);
      }
   }
}

另外:委托对象的一个有用属性是,它们可以“+”运算符来组合。组合的委托可调用组成它的那两个委托。只有相同类型的委托才可以组合。

“-”运算符可用来从组合的委托移除组件委托。
// compose.cs
using System;

delegate void MyDelegate(string s);

class MyClass
{
    public static void Hello(string s)
    {
        Console.WriteLine("  Hello, {0}!", s);
    }

    public static void Goodbye(string s)
    {
        Console.WriteLine("  Goodbye, {0}!", 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:
        c = a + b;
        // Remove a from the composed delegate, leaving d,
        // which calls only the method Goodbye:
        d = c - a;

        Console.WriteLine("Invoking delegate a:");
        a("A");
        Console.WriteLine("Invoking delegate b:");
        b("B");
        Console.WriteLine("Invoking delegate c:");
        c("C");
        Console.WriteLine("Invoking delegate d:");
        d("D");
    }
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值