none
再请周版主分析一段代码! RRS feed

  • 问题

  • namespace Bookstore
    {
      using System.Collecting;
      //定义图书信息
      struct Book
      {
        public string Title;
        public string Author;
        public double Price;
        public bool Paperback;//是否是平装书
       public Book(string title,string author,string price,bool paperback)
         {
           Title=title;
           Author=author;
           Price=price;
           Paperback=paperback;
         }
      }
      //声明委托
      public  delegate void ProcessBookDelegate(Book book);
      class BookDB
      {
        ArrayList list=new ArrayList();
        //增加图书
        public void AddBook(string title,string author,string price,bool paperback)
        {
          list.Add(new Book(title,author,price,paperback));
        }
         //循环扫描书库,若是平装书为其分配一个委托
       public void ProcessPaperBook(ProcessBookDelegate DelegateBook)
        {
           foreach(Book book in list)
           {
             if(book.Paperback)
             {
                DelegateBook(book);
             }
           }
        }
      }
    }
    namespace TestCLient
       {
       using Bookstore;
       class PriceTotaller
       {
         private int countBooks;//平装书个数
       private double priceBooks;//平装书总价
       public void  AddBookToTaller(Book book)
        {
         countBooks+=1;
         priceBooks+=book.Price;
        }
        public double AveragePrice()
        {
          return priceBooks/countBooks;
        }
       }
       class Test
       {
         static void PrintTitle(Book book)
         {
           System.Console.WriteLine(book.Title);
         }
         static void Main()
         {
          BookDB bdb=new BookDB();
          AddBooks(bdb);//向书库增加一些图书
           bdb.ProcessPaperBook(PrintTitle);
          PriceTotaller totaller=new PriceTotaller();
          bdb.ProcessPaperBook(totaller.AddBookToTaller);
          System.Console.WriteLine("平均书价:{0}",totaller.AveragePrice());
         }
         static void AddBooks(BookDB bdb)
         {
          bdb.AddBook("图书一","作者一",100,True);
          bdb.AddBook("图书二","作者二",100,True);
          bdb.AddBook("图书三","作者三",100,False);
          bdb.AddBook("图书四","作者四",100,False);
         }
       }
    }
    
    
    
    
    
    
    
    
    昨天才看的委托,我是这样理解的:
      声明委托后,Main()函数中,先给委托传递PrintTitle方法,若查到平装书则输出标题,再实例化PriceTotaller类,将AddBookToTaller方法传递给委托,最后统计平均单价。

    但是还是想请周版主详细的分析一下。感谢。
    2010年2月2日 3:29

答案

  • 周周不在,我大概看了一下,你理解的没有错,对,加油
    结果:先打印出平装书,再计算平均值

    为东北家乡的同事和学弟们服务,希望你们每个人都能生活的好好的。
    感谢你们的帮助,我要把你们给我的帮助传递给更多的人。
    http://terryfeng.cnblogs.com http://www.terryfeng.com
    2010年2月2日 6:59
  • 你好!感谢冯的及时回复啊!
    你理解的基本正确,我这里补充一点:
    bdb.ProcessPaperBook(totaller.AddBookToTaller);
    是把totaller这个对象的AddBookToTaller方法赋给委托实例,是谁的哪个方法需要注意一下!
    周雪峰
    2010年2月2日 8:51
    版主

全部回复

  • 周周不在,我大概看了一下,你理解的没有错,对,加油
    结果:先打印出平装书,再计算平均值

    为东北家乡的同事和学弟们服务,希望你们每个人都能生活的好好的。
    感谢你们的帮助,我要把你们给我的帮助传递给更多的人。
    http://terryfeng.cnblogs.com http://www.terryfeng.com
    2010年2月2日 6:59
  • 你好!感谢冯的及时回复啊!
    你理解的基本正确,我这里补充一点:
    bdb.ProcessPaperBook(totaller.AddBookToTaller);
    是把totaller这个对象的AddBookToTaller方法赋给委托实例,是谁的哪个方法需要注意一下!
    周雪峰
    2010年2月2日 8:51
    版主
  • 谢谢,再请问周版主个问题,这里的委托ProcessBookDelegate DelegateBook只是声明一下,为什么事件里的委托都要实例化呢? 例如EventName+=new DelegateName(method);

    2010年2月3日 6:08
  • 不客气啊!
    是这样的,比如这行代码:
    bdb.ProcessPaperBook(totaller.AddBookToTaller);
    这里是把totaller.AddBookToTaller来初始化方法的参数DelegateBook,实际上这行代码是下面代码的简写形式:
    bdb.ProcessPaperBook(new ProcessBookDelegate(totaller.AddBookToTaller));
    在.NET Framework 1.1版本的时候,必须要写成第二种形式,从.NET Framework 2.0开始,提供了第一种形式的简略语法!C#的编译器能够知道这个方法是用来初始化一个委托实例或事件的!
    实际上事件的订阅也可以直接这样:
    EventName+=method;
    这种现象有个叫法:语法糖,只是在语法上简化,令人感觉很甜蜜,而实质上没有任何的区别!
    在减轻我们的代码输入量的同时,过于简化的语法可能会令人难以理解,任何事物都有两面性啊!

    周雪峰
    • 已建议为答案 mazhou 2010年2月3日 9:55
    2010年2月3日 6:53
    版主
  • 恩  最近深入看了委托和事件,把以前的WinForm源码拿来看才顿时茅塞顿开,比如一个控件的事件,以前只知道双击进入其事件,开始写相应代码,根本没弄清为什么。
    此外还想问一下:
    1,很多控件的事件都是基于EventHandler这个委托的,为什么?
    2,比如我自己定义一个事件,在需要调用的时候 changed(参数实例);进行调用,但是比如Button点击会产生事件,但是怎么没有调用事件Click(参数实例);这句代码,只是有ButtonName_Click(object sender,EventArgs e){}事件处理方法呢?

    2010年2月4日 4:15
  • 你好!
         1,EventHandler这个类是所有事件的委托类型的基类,提供为事件提供了一个基本的委托类型!
         2,当然有触发事件的代码,都是在protected的方法中触发的,触发Click的方法是OnClick
    周雪峰
    2010年2月4日 4:35
    版主
  • 在哪可以看到触发的代码?

    2010年2月4日 4:57
  • 触发Click事件的代码是写在OnClick这个方法中的,也就是查看类库中的源代码就可以看到!
    周雪峰
    2010年2月4日 6:24
    版主
  • 事件的触发,是被观察的类触发,而我们的事件只不过是注册在了被观察类的事件上,具体的如何触发,如果是你自己写的代码,你就应该知道什么情况下触发,而如果是。NET的或者第三方的控件之类的,就是它内部的方法了,如果不开源的话,我们是看不到了,只能注册上去而已
    2010年2月5日 2:04
  • 如果想理解.NET的事件机制,你可以好好去看看设计模式里的观察者模式,观察着模式中分为两种实现,一种是“推方法“,另一种是”拉方法“,而.net为CODER实现这两种方法,以便让
    CODER可以根据自己的喜好来使用时间,在事件中object sender 和eventhArg e这两个分别是上面2种方法所需要的值,前者是将所被观察的对象传递过来,而后者是将观察着所关心的信息传递过来。而你所说的没有什么事件,事件是由被观察对象所发布的,如果没有对象没有发布,也没有办法,除非你自己重写。
    2010年2月5日 2:09