迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
事件是利用委托来定义的,因此先解释委托。委托其实是一个类,它与其他类如string(引用类型)等没有本质区别,string代表的是字符串,委托则代表的是一类方法,这类方法具有相同返回类型和相同参数。例:有如下委托定义 public delegate void CalculatorHandler(int x,int y);
从CalculatorHandler这个委托的定义可以看出,它反应的是一类方法,这类方法的返回类型是void,两个参数是(int x,int y),因此以后所有具有这样特征的方法都可以用这个委托来代替,现有以下这个方法: static void Add(int x, int y) { Console.WriteLine("x+y={0}",x+y); } 这个方法,满足委托所定义的这一类方法,但是如何利用委托来调用这个方法呢,首先要将这个方法赋值给这个委托才可以使用,就如普通的类赋值一样, CalculatorHandler calhandler = new CalculatorHandler(Add) 当然你也可以像给一个字符串赋值一样,这样给委托赋值: CalculatorHandler calhander = Add; 当要调用这个方法的时候,你可以就像使用方法一样使用委托, calhander(3,4); 委托也可以绑定多个方法,当调用这个委托时,会调用所有已经绑定了的方法,如现在还有这样的方法: static void Multiply(int x, int y) { Console.WriteLine("x*y={0}",x*y); } 只需在calhandler基础上多绑定个方法,具体语法: calhander += Multiply; 这样当调用 calhander(3,4); 会同时调用Add和Multiply这两个方法,你也可以利用“-=”解绑方法: calhander -= Multiply; 这样再次调用这个委托,则只会调用Add这个方法。 2. 事件 一说到事件总会有发布者(publisher)和订阅者(subscriber),发布者定义了一个事件,订阅者订阅了该事件(指的是当该事件触发时,订阅者做出什么样的反应,即利用相应的函数去处理)。该函数的定义与定义该事件的委托必须配套。代码如下: public delegate void MessageEventHandler(); class Publisher { public event MessageEventHandler MessageEvent; public void DoSomething() { Console.WriteLine("等待消息"); Console.WriteLine("首长来啦!!!"); OnMessageEvent(); } public void OnMessageEvent() { if (MessageEvent != null) { MessageEvent(); } } } class Subscriber { public Subscriber(Publisher p) { p.MessageEvent += Response; } public void Response() { Console.WriteLine("首场,辛苦了"); } } class Program { static void Main(string[] args) { Publisher p = new Publisher(); Subscriber s = new Subscriber(p); p.DoSomething(); Console.ReadKey(); } } } 这就是事件的基本用法,但是事件与委托到底有什么区别呢,从上面的代码可以看出,事件是根据委托来定义的, public event MessageEventHandler MessageEvent 其实它是利用委托来规定订阅者处理函数的类型(相同的返回类型和参数即为一类),然后方便在发布者自身的类中来触发订阅者的这些函数。 但是为什么要事件呢,要实现这些,我仅用委托也可以实现呀,如下代码: public delegate void MessageEventHandler(); class Publisher { public MessageEventHandler MessageEvent;//为了方便,委托名与原来的事件名相同。 // public event MessageEventHandler MessageEvent; public void DoSomething() { Console.WriteLine("等待消息"); Console.WriteLine("首长来啦!!!"); OnMessageEvent(); } public void OnMessageEvent() { if (MessageEvent != null) { MessageEvent(); } } } class Subscriber { public Subscriber(Publisher p) { p.MessageEvent += Response; } public void Response() { Console.WriteLine("首场,辛苦了"); } } class Program { static void Main(string[] args) { Publisher p = new Publisher(); Subscriber s = new Subscriber(p); p.DoSomething(); Console.ReadKey(); } } 这样子也同样可以产生相同的结果。 但是当客户端如下调用呢? Publisher p = new Publisher(); Subscriber s = new Subscriber(p); p.DoSomething(); p.MessageEvent(); Console.ReadKey(); 客户端是不是能随意让发布者产生事件,因此我们可否将发布者的委托定义为private,因为只有发布者的内部才能触发事件嘛,其他人怎么可以?但是这样订阅者就无法订阅了,那我们是否可以增加绑定和解除的函数来订阅此委托呢? public delegate void MessageEventHandler(); class Publisher { private MessageEventHandler MessageEvent; // public event MessageEventHandler MessageEvent; public void DoSomething() { Console.WriteLine("等待消息"); Console.WriteLine("首长来啦!!!"); OnMessageEvent(); } public void OnMessageEvent() { if (MessageEvent != null) { MessageEvent(); } } public void Add_MessageEvent(MessageEventHandler m) { MessageEvent += m; } public void Reomove_MessageEvent(MessageEventHandler m) { MessageEvent -= m; } } class Subscriber { public Subscriber(Publisher p) { //p.MessageEvent += Response; p.Add_MessageEvent(Response); } public void Response() { Console.WriteLine("首场,辛苦了"); } } class Program { static void Main(string[] args) { Publisher p = new Publisher(); Subscriber s = new Subscriber(p); p.DoSomething(); Console.ReadKey(); } } } 这样就可以实现与事件一样的功能,因此为了方便微软为我们提供了事件访问器,何为事件访问器? public delegate void MessageEventHandler(); class Publisher { private MessageEventHandler MessageEvent; // public event MessageEventHandler MessageEvent; public event MessageEventHandler TestEvent { add { lock (MessageEvent) { MessageEvent += value; } } remove { lock (MessageEvent) { MessageEvent -= value; } } } public void DoSomething() { Console.WriteLine("等待消息"); Console.WriteLine("首长来啦!!!"); OnMessageEvent(); } public void OnMessageEvent() { if (MessageEvent != null) { MessageEvent(); } } } class Subscriber { public Subscriber(Publisher p) { p.TestEvent += Response; } public void Response() { Console.WriteLine("首场,辛苦了"); } } class Program { static void Main(string[] args) { Publisher p = new Publisher(); Subscriber s = new Subscriber(p); p.DoSomething(); Console.ReadKey(); } } 以上的代码就是利用事件访问器来让委托绑定订阅者的方法,事件访问器中的add和remove能自动编译为+=和-=。 通过reflector,我们可以看到一个事件是如何定义的: 它是申明一个私有的委托: private MessageEventHandler MessageEvent;
另外利用两个函数来绑定与解除订阅者的方法。
|
请发表评论