C#OOP之十一 委托和事件_事件机制


委托的概念

在日常生活中我们使用委托机制来处理问题,比如,委托别人帮自己买饭、委托基金公司帮助自己打点财产、委托律师打官司等。在C#中,委托技术可以讲一个方法委托给一个对象,此后这个对象便可全权代理这个方法的执行了,这一点和我们日常生活中委托的概念类似。


委托的声明:

       ​【特性】【修饰符】delegate【返回类型】【委托名】(【参数化列表】)

委托时一种引用类型,封装了对方法的引用。

委托的使用步骤:

1.      声明委托

2.      实例化委托

3.      使用委托

案例1:使用委托来让某人买东西

/*

我们使用的是在委托中:对象.方法名;类名.方法名;委托;

*/

using System;

namespace DelegateTest

{

public delegate void MyDelegate();          //1.声明委托


class Person

{

       //方法:委托和需要委托对象|类的方法的返回类型必须一致;

       publicvoid buy()

       {

              Console.WriteLine("我去买东西了");

       }

}

class Test

{

       staticvoid Main()

       {

              Personguodesai=new Person(); //人类的一个对象郭德赛;

              MyDelegatebuyPaoPaoTang=new MyDelegate(guodesai.buy);         //2.实例化委托:委托郭德赛去买东西;对象.方法名称;(不需要小扩号)

              getTang(buyPaoPaoTang);   //3:使用委托

       }    

       publicstatic void getTang(MyDelegate obj)

       {

              obj();

       }

}

}

通过上面的案例,我们更明确了委托时引用类型,需要被new一下,然后才可以使用。






委托的奥秘






委托和类都是引用类型,在定义委托之后,系统编译时系统会自动创建一个委托类。要查看委托的本质,需要借助于ILDasm.exe来查看刚才DelegateBuy委托生成的中间代码,得到结果如下图所示:

C#OOP之十一 委托和事件_委托事件_02

在源代码只有Person和Test两个类,那么剩下的MyDelegate类是从哪里来的呢?就是我们上面定义的委托类型MyDelegate编译后的结果。仔细观察就会发现,委托类实际上就是一个继承自MulticastDelegate基类的一个自定义类。



多播委托






多播委托时委托的一种特殊应用,多播委托允许将多个委托对象组成一个委托链。关于“链”的叫法在这里也形象地表示了多播委托的意义,”链”类似于“多米诺骨牌”或者我们平时说的连锁反应。委托链的作用也是这样,委托链可以承载多个方法,一旦触发该链,那么将调用链中的所有方法。创建一个多播委托和创建普通委托没有区别,可以使用“+”号运算符把委托对象加入委托从而形成委托链,利用“-”运算符从委托链移除一个委托。

案例:使用多播委托来实现计算器的计算功能

/*

通过委托机制来实现计算器

委托必须和方法的返回类型和方法签名一致;

多播委托来实现一个委托对象来实现多个操作!!!

*/

usingSystem;

namespace  Test

{

     //1.声明委托

     public delegate void CalcDelegate(doublenum1,double num2);

     //计算器类

     class Calc

     {

            public void Add(double num1,doublenum2)

            {

                   Console.WriteLine("{0}+{1}=为:{2}",num1,num2,num1+num2);

            }    

            public void Subtract(doublenum1,double num2)

            {

                   Console.WriteLine("{0}-{1}=为:{2}",num1,num2,num1-num2);  

            }    

            public void Multiply(doublenum1,double num2)

            {

                   Console.WriteLine("{0}*{1}=为:{2}",num1,num2,num1*num2);        

            }    

            public void Divide(doublenum1,double num2)

            {    

                   if(num2==0)

                          Console.WriteLine("除数不能为0");

                   else

                          Console.WriteLine("{0}/{1}=为:{2}",num1,num2,num1/num2);  

            }    

     }

     class GUI

     {

            static void Main()

            {

                   Calc MobileCalc=new Calc();            //声明并实例化一个手机上的Calc类对象;


                   CalcDelegate myDele=newCalcDelegate(MobileCalc.Add);  //不需要放数                           

                   myDele+=newCalcDelegate(MobileCalc.Subtract);

                   myDele+=newCalcDelegate(MobileCalc.Multiply);

                   myDele+=newCalcDelegate(MobileCalc.Divide);

                   //myDele-=new CalcDelegate(MobileCalc.Divide);

                   myDele(5.5,3.3);

            }

     }

}

在上面的代码中,我们定义了一个名称为myDele的委托对象,然后我们使用三个“+”号将三个方法的委托对象分别加入到myDele的委托当中,从而形成委托链。当我们使用myDele(5.5,3.3)时候,会依次调用三个方法。

注意:

1.如果把myDele-那行的注释去掉会发生何种效果;

2.多播委托的委托方法最好是没有返回值的方法,也就是void方法,如果委托带有返回值的方法,也无法获得级联的结果;

3.多播委托只支持+、-、+=、-=四种运算。



事件






事件就是突然发生的事,古有安史之乱,今有卢沟桥兵变都属于事件。当然这些都是比较明显的事件,在现实生活中,如“要是发钱,我们就很兴奋”,其中发钱就是事件,我们兴奋就是事件发生后引发的精神反应。又假如,你上班迟到了,被老板罚了100块大洋,此时,你上班迟到和被老板罚款都是事件,你迟到了,老板为了严肃军纪,罚你钱的事件产生了;罚你钱后,你的心情很沮丧。

现实生活的事件数不胜数,总结我们举得案例,不难归纳出一个事件从发生到结束涉及到四个要素:什么事件、事件的发布者、事件的接收者、事件引发的处理动作。

事件机制的原理

我们说的事件机制就是指事件四要素有机结合构成的一种机制。事件的发布者定义和发布事件,比如“台独”事件就是由阿扁定义和发布的。

事件的接收者接收事件并引发事件处理动作,并且事件的接收者可以对事件做出不同的处理。

假如你就是“台独”事件的接收者,你听了之后直接拿着棒子去找阿扁,而别人可能就不这么做。

计算机中的事件机制就是现实生活中这种事件机制的模拟和抽象。此时你可能会问,计算机有哪些事件呢?通常鼠标移动、键盘敲击、网络中毒等都属于事件。

计算机中的事件运行机制更像日常生活中的订阅活动。

在这里我们认为报纸就是事件,首先你要去邮局订阅报纸,然后报纸才能发送到你手里,再然后,你看了报纸会做出反应,就是事件的处理。

根据上面的分析,我们将事件接收者和发送者的职责归纳如下:

事件的发布者职责:

n        定义事件

n        为订阅者订阅该事件

n        将发生的事件通知给订阅对象

事件的订阅者(接收者)职责:

n        接收事件

n        处理事件

事件的定义:

【访问修饰符】event   委托类型   事件对象

public delegate void delegateCar(string msg);  //委托定义

private event   delegateCar  eventCar;   //eventCar事件

事件接收者类:CarHandler,要接收事件就必须在事件的接受者类里提供和事件定义时委托类型相同的方法。

class CarHandler

{

       //定义事件处理方法

       publicvoid HandlerEvent(string msg)

       {

              Console.WriteLine(msg);

}

}

事件的订阅通过“+=”操作符,事件的订阅和多播委托一样,可以给事件添加一个或多个方法委托。如下:

class Car

{

       publicdelegate void delegateCar(string msg);

       privateevent delegateCar eventCar;

       publicInit (CarHandler obj)

       {//订阅事件

              eventCar+=newdelegateCar(obj.HandlerEvent);

}

}

上面的代码中,我们在Car类内部为事件对象obj订阅了一个事件。订阅完事件后,事件发布者还需要激发事件,一旦事件被激发,事件的接收者就会自动接收事件,然抽处理事件。

处理事件三步骤:

1.      定义事件

2.      订阅事件

3.      激发事件







项目1:模拟刹车







usingSystem;

usingSystem.Text;

NamespaceMyDelegate

{

       class Car

       {

       public delegate void delegateCar(string msg);

       //定义刹车事件

       public event delegateCar eventCar;

       public void Stop()

       {

              //激发刹车事件

              eventCar(“刹车!”);

}

}

class CarHandler

{

  //定义事件处理方法

  publicvoid HandlerEvent(string msg)

  {

         Console.WriteLine(msg);

}

}

class Program

{

  publicstatic void Main(string[]args)

  {

         Carcar=new Car();

         CarHandlerhandler=new CarHandler();

         car.eventCar+=newCar.delegateCar(handler.HandlerEvent);

         car.Stop();

}

}

}

目前,我们还感觉不到事件机制太多的好处,实际上Windows的编程技术都是建立在事件基础上的,Web Form、WinForm、WPF等编程都是以事件机制为基础的。如此一来,理解事件机制的本质含义就显得尤为重要。事件机制在内部是通过多播委托来实现的,为了更好的理解事件,系统为我们提供了event关键字。


事件的定义分定义事件、订阅事件、激发事件这三步。下面的案例用程序模拟警察抓小偷的过程,可以更形象的说明事件使用的方法。

C#OOP之十一 委托和事件_c#_03


程序模拟:


usingSystem;

usingSystem.Text;


namespaceMyNameSpace

{

       class 小偷

       {

       public void 跑(){Console.WriteLine(“小偷跑了”);}

}

class 警察

       {

       public void 追(){Console.WriteLine(“警察追”);}

}

class 银行

{

public delegate void ActDelegate();

public event ActDelegate 警铃事件;

public void 警铃响(){警铃事件();}

}

      class Program

      {

       public static void Main(string[]args)

       {

       银行   bank=new 银行();

       小偷   zei=new 小偷();

       警察   jingcha1=new 警察();

       警察   jingcha2=new 警察();


       bank.警铃事件+=zei.跑;

       bank.警铃事件+= jingcha1.追;

bank.警铃事件+= jingcha2.追;


bank.警铃响();

}

}

}







小结:






在本章中,我们主要学习了:

u      委托的概念和使用

u      多播委托

u      事件的定义和使用






英语词汇:






英文            全文                                        中文

Delegate                                           代理、委托

Fuction                                             函数

Event                                                       事件

Occur                                                      发生

Object                                                     对象

Nofity                                                      通知

Everyone                                                 大家,所有人

Listen                                                      听

Act                                                   实行,反应

Declare                                            声明

Scriber                                                    划线器

Handler                                            处理者

Alarm                                                      警报,闹铃

Hour                                                       时

Minute                                                     分

Second                                                    秒

Reason                                                    原因

Log                                                  日志,写日志

Attendance                                              维护

Trigger                                                    跟踪

Multiply                                            多的






练习项目:






1.利用委托和事件实现,键盘敲击事件的模拟,当单击A~Z字母时候,现实相应的字母(这端代码可以使用输出语句来代替)。