关于C#事件和委托的一点体会

来源:互联网 发布:黑马python 编辑:程序博客网 时间:2024/04/29 17:41
 下面这段代码为:

/******************************************************************************
Module:  MailManager.cs
Notices: Copyright (c) 2002 Jeffrey Richter
******************************************************************************/


using System;


///////////////////////////////////////////////////////////////////////////////


class MailManager
{
    public classProcessMailMsgEventArgs : EventArgs
    {

       // 1. Type defining information passed to receivers of theevent
       public ProcessMailMsgEventArgs(
          String from, String to, String subject, String body)
       {

           this.from = from;
           this.to = to;
           this.subject = subject;
           this.body = body;
       }

       public readonly String from, to, subject, body;
    }

    // 2.Delegate type defining the prototype of the callback method
   //    thatreceivers must implement
    publicdelegate void ProcessMailMsgEventHandler(
      Object sender, ProcessMailMsgEventArgs args);

    // 3. Theevent itself
    public eventProcessMailMsgEventHandler ProcessMailMsg;

    // 4.Protected, virtual method responsible for notifyingregistered
   //    objects ofthe event
    protectedvirtual void OnProcessMailMsg(ProcessMailMsgEventArgs e)
    {

       // Has any objects registered interest with our event?
       if (ProcessMailMsg != null)
       {

           // Yes, notify all the objects
           ProcessMailMsg(this, e);  //激发事件,将消息传递给订阅此事件的所有对象
       }
    }

    // 5.Method that translates the input into the desired event
   //    Thismethod is called when a new e-mail message arrives
    public voidSimulateArrivingMsg(String from, String to,
      String subject, String body)
    {

       // Construct an object to hold the information we wish
       // to pass to the receivers of our notification
       ProcessMailMsgEventArgs e =
          new ProcessMailMsgEventArgs(from, to, subject, body);

       // Call our virtual method notifying our object that theevent
       // occurred. If no type overrides this method, our objectwill
       // notify all the objects that registered interest in theevent
       OnProcessMailMsg(e);
    }
}


///////////////////////////////////////////////////////////////////////////////


class Fax
{
    // Pass theMailManager object to the constructor
    publicFax()
    {

    }

    // Thisis the method that the MailManager will call
    // when anew e-mail message arrives
    publicvirtual void FaxMsg(
      Object sender, MailManager.ProcessMailMsgEventArgs e)
    {

       // 'sender' identifies the MailManager in case
       // we want to communicate back to it.

       // 'e' identifies the additional event information
       // that the MailManager wants to give us.

       // Normally, the code here would fax the e-mail message.
       // This test implementation displays the info on the console
       Console.WriteLine("Faxing mail message:");
       Console.WriteLine(
            To:{0}\n   From:{1}\n   Subject:{2}\n   Body: {3}\n",
          e.from, e.to, e.subject, e.body);
    }

    publicvoid Register(MailManager mm)
    {

       // Construct an instance of the ProcessMailMsgEventHandler
       // delegate that refers to our FaxMsg callback method.
       MailManager.ProcessMailMsgEventHandler callback =
          new MailManager.ProcessMailMsgEventHandler(FaxMsg);

       mm.ProcessMailMsg+= callback;
    }
    public voidUnregister(MailManager mm)
    {

       // Construct an instance of the ProcessMailMsgEventHandler
       // delegate that refers to our FaxMsg callback method.
       MailManager.ProcessMailMsgEventHandler callback =
          new MailManager.ProcessMailMsgEventHandler(FaxMsg);

       // Unregister ourself with MailManager's ProcessMailMsg event
       mm.ProcessMailMsg -= callback;
    }
}

class Fax1 : Fax
{
    publicoverride  void FaxMsg(
     Object sender, MailManager.ProcessMailMsgEventArgs e)
    {

       // 'sender' identifies the MailManager in case
       // we want to communicate back to it.

       // 'e' identifies the additional event information
       // that the MailManager wants to give us.

       // Normally, the code here would fax the e-mail message.
       // This test implementation displays the info on the console
       Console.WriteLine("Faxing1 mail message:");
       Console.WriteLine(
            To:{0}\n   From:{1}\n   Subject:{2}\n   Body: {3}\n",
          e.from, e.to, e.subject, e.body);
    }

}
///////////////////////////////////////////////////////////////////////////////


class Pager
{
    // Pass theMailManager object to the constructor
    publicPager(MailManager mm)
    {

       // Construct an instance of the ProcessMailMsgEventHandler
       // delegate that refers to our SendMsgToPager callbackmethod.
       // Register our callback with MailManager's ProcessMailMsgevent
       mm.ProcessMailMsg +=
          new MailManager.ProcessMailMsgEventHandler(SendMsgToPager);
    }

    // Thisis the method that the MailManager will call
    // when anew e-mail message arrives
   private  void SendMsgToPager(
      Object sender, MailManager.ProcessMailMsgEventArgs e)
    {

       // 'sender' identifies the MailManager in case
       // we want to communicate back to it.

       // 'e' identifies the additional event information
       // that the MailManager wants to give us.

       // Normally, the code here would send the e-mail message to apager.
       // This test implementation displays the info on the console
       Console.WriteLine("Sending mail message to pager:");
       Console.WriteLine(
            To:{0}\n   From:{1}\n   Subject:{2}\n   Body: {3}\n",
          e.from, e.to, e.subject, e.body);
    }
}


///////////////////////////////////////////////////////////////////////////////


class App
{
    static voidMain()
    {
       // Construct a MailManager object
       MailManager mm = new MailManager();

       // Construct a Fax object passing it the MailManager object
       Fax fax = new Fax();
       Fax fax1 = new Fax1();
       fax.Register(mm);
       fax1.Register(mm);
       // Construct a Pager object passing it the MailManager object
       Pager pager = new Pager(mm);

       // Simulate an incoming mail message
       mm.SimulateArrivingMsg("Jeffrey Richter",
          "Santa",
          "Christmas",
          "Thanks for the great presents last year");

       // Force the Fax object to unregister itself with theMailManager
       fax.Unregister(mm);

       // Simulate an incoming mail message
       mm.SimulateArrivingMsg("Jeffrey Richter", "Mom & Dad",
          "My birthday",
          "Thanks for the great presents last year");

    }
}

执行结果如下:

Faxing mailmessage:
   To:Jeffrey Richter
   From: Santa
   Subject: Christmas
   Body: Thanks for the greatpresents last year

Faxing1 mailmessage:
   To: Jeffrey Richter
   From: Santa
   Subject: Christmas
   Body: Thanks for the greatpresents last year

Sending mail message to pager:
   To: Jeffrey Richter
   From: Santa
   Subject: Christmas
   Body: Thanks for the greatpresents last year

Faxing1 mail message:
   To: Jeffrey Richter
   From: Mom & Dad
   Subject: My birthday
   Body: Thanks for the greatpresents last year

Sending mail message to pager:
   To: Jeffrey Richter
   From: Mom & Dad
   Subject: My birthday
   Body: Thanks for the greatpresents last year

 

注意上面红颜色部分,出现这样输出结果的原因是名为FaxMsg委托方法是虚方法,而将委托方法改为虚函数,则不会有任何影响。

在C/C++中,非静态成员函数是不同作为回调函数的,因为非静态成员函数成员函数与具体的对象有关系,所以我最初很不能理解为什么FaxMsg可以用作回调函数,最近似乎有所领悟,那就是在把委托实例加入事件的委托链时,除了将方法的地址传入外,同时也将this指针传入了,这部分工作应该是编译器完成的。如果是虚方法,则动态绑定方法的地址。如果是静态方法,则忽略this指针。

这样,上面的代码就好理解了,我估计应该是这样的,不知道对不对,也许《AppliedMicrosoft.NET FrameworkProgramming》中会讲到,不过我还没有看到那么远。到时候再验证吧。

0 0
原创粉丝点击