C#事件与委托的区别
C#事件与委托的区别
1. 委托
事件是利用委托来定义的,因此先解释委托。委托是一个类,它与其他类如int,string等没有本质区别,int代表的是所有的整形,而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;
另外利用两个函数来绑定与解除订阅者的方法。
C#事件与委托的区别的更多相关文章
- C# 事件和委托
相信大家在面试的时候会经常问到事件和委托的区别,为什么.net中需要事件和委托这样类似的问题吧,对于一些初学者来说可平时用的过程中也不知道为什么, 只知道这样用,而对于其中的实现机制不是很清楚, 所以 ...
- 事件、委托、委托方法的总结(使用EventHandler<>)
在C#中,定义事件.委托.委托方法可以使用类库内的EventHandler泛型委托来定义事件.并根据该泛型委托定义实现方法: 同样您也可以自定义委托 来定义事件以及 根据自定义的委托来定义实现事件的方 ...
- C#基础精华07(委托事件,委托的使用,匿名方法)
1.委托概述 委托是一种数据类型,像类一样(可以声明委托类型变量).方法参数可以是int.string.类类型 void M1(int n){ } √ void M2(string s){ } √ ...
- [C#参考]事件和委托的关系
前面说了委托,接下来就要说一说事件了,同时最后再说一下委托和事件的区别. 事件和委托很相似,事件就好像是被简化的针对特殊用途的委托.看下面的图: 从这张图中能看到,事件是发布者的一个成员,它不是类型. ...
- C#事件与委托详解【精华 多看看】
Delegate delegate是C#中的一种类型,它实际上是一个能够持有对某个方法的引用的类.与其它的类不同,delegate类能够拥有一个签名(signature),并且它"只能持有与 ...
- C#基础知识之事件和委托
本文中,我将通过两个范例由浅入深地讲述什么是委托.为什么要使用委托.委托的调用方式.事件的由来..Net Framework中的委托和事件.委托和事件对Observer设计模式的意义,对它们的中间代码 ...
- 解密jQuery事件核心 - 委托设计(二)
第一篇 http://www.cnblogs.com/aaronjs/p/3444874.html 从上章就能得出几个信息: 事件信息都存储在数据缓存中 对于没有特殊事件特有监听方法和普通事件都用ad ...
- c#事件与委托
C#.net 目录(?)[-] 将方法作为方法的参数 将方法绑定到委托 事件的由来 事件和委托的编译代码 委托事件与Observer设计模式 范例说明 Observer设计模式简介 实现范例的Obse ...
- 《C#高级编程》学习笔记------C#中的事件和委托
本文转载自张子阳 目录 委托的作用 将方法绑定到委托 事件的来由 Observer设计模式 .Net Framework中的委托与事件 引言 委托 和 事件在 .Net Framework中的应用 ...
随机推荐
- 讨论oracle在rowid和rownum
[ 概要 ] 刚刚接触oracle的同学可能经常会被rowid和rownum这两个词弄混, 弄清楚这两个家伙对于我们写sql会有非常大的帮助, 以下偶就抛砖引玉, 简单地谈谈他们之间的差别吧. [ 比 ...
- java一般使用基础
1.这是一个通用 仿制药javaA型安全机制来保护. 它是通过变量的类型,如果,实现变量类型限制,从而保证了程序编译变量类型的安全性在一定程度上.反之.如果没有泛型,这些只存在于程序,如果猿的大脑,这 ...
- 杭电1162Eddy's picture
Eddy's picture Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) Tota ...
- linux_安装 redis
Installation Download, extract and compile Redis with: $ wget http://download.redis.io/releases/redi ...
- ArcGIS网络分析之Silverlight客户端最近设施点分析(四)
原文:ArcGIS网络分析之Silverlight客户端最近设施点分析(四) 在上一篇中说了如何实现最近路径分析,本篇将讨论如何实现最近设施点分析. 最近设施点分析实际上和路径分析有些相识,实现的过程 ...
- MySQL检查连接的最大数量和改变的最大连接数
版权声明:本文博主原创文章.博客,未经同意不得转载.
- Swift语言指南(八)--语言基础之元组
原文:Swift语言指南(八)--语言基础之元组 元组 元组(Tuples)将多个值组合为一个复合值.元组内的值可以是任何类型,各个元素不需要为相同类型(各个元素之间类型独立,互不干扰--Joe.Hu ...
- 为什么使用Hystrix?
分布式服务弹性框架“Hystrix”实践与源码研究(一) 文章初衷 为了应对将来在线(特别是无线端)业务量的成倍增长,后端服务的分布式化程度需要不断提高,对于服务的延迟和容错管理将面临更大挑战,公 ...
- 合并多段zip文件并解压缩
cat xxx.zip.*** >xxx.zip unzip xxx.zip
- iOS 学习
iOS 学习资料 (适合初学者) 本文资料来源于GitHub 一.视频教程(英文) Developing iOS 7 Apps for iPhone and iPad斯坦福开放教程之一, 课程主要讲解 ...