C#事件与委托的区别

1. 委托

事件是利用委托来定义的,因此先解释委托。委托是一个类,它与其他类如int,string等没有本质区别,int代表的是所有的整形,而string代表的是字符串,委托则代表的是一类方法,这类方法具有相同返回类型和相同参数。委托的定义:

  1. public delegate void CalculatorHandler(int x,int y);

从CalculatorHandler这个委托的定义可以看出,它反应的是一类方法,这类方法的返回类型是void,两个参数是(int x,int y),因此以后所有具有这样特征的方法都可以用这个委托来代替,现有以下这个方法:

  1. static void Add(int x, int y)
  2. {
  3. Console.WriteLine("x+y={0}",x+y);
  4. }

首先要将这个方法赋值给这个委托才可以使用,就如普通的类赋值一样,

CalculatorHandler calhandler = new CalculatorHandler(Add)

当然你也可以像给一个整形赋值一样,这样赋值:

CalculatorHandler calhander = Add;

当要调用这个方法的时候,你可以就像使用方法一样使用委托,

calhander(3,4);

委托也可以绑定多个方法,当调用这个委托时,会调用所有已经绑定了的方法,如现在还有这样的方法:

  1. static void Multiply(int x, int y)
  2. {
  3. Console.WriteLine("x*y={0}",x*y);
  4. }

只需在calhandler基础上多绑定个方法,具体语法:

calhander += Multiply;

这样当调用

calhander(3,4);

会同时调用Add和Multiply这两个方法,你也可以利用“-=”解绑方法:

calhander -= Multiply;

这样再次调用这个委托,则只会调用Add这个方法。

2. 事件

一说到事件总会有发布者(publisher)和订阅者(subscriber),发布者定义了一个事件,订阅者订阅了该事件(指的是当该事件触发时,订阅者做出什么样的反应,即利用相应的函数去处理)。该函数的定义与定义该事件的委托配套。代码如下:

  1. public delegate void MessageEventHandler();
  2. class Publisher
  3. {
  4. public event MessageEventHandler MessageEvent;
  5. public void DoSomething()
  6. {
  7. Console.WriteLine("等待消息");
  8. Console.WriteLine("首长来啦!!!");
  9. OnMessageEvent();
  10. }
  11. public void OnMessageEvent()
  12. {
  13. if (MessageEvent != null)
  14. {
  15. MessageEvent();
  16. }
  17. }
  18. }
  19. class Subscriber
  20. {
  21. public Subscriber(Publisher p)
  22. {
  23. p.MessageEvent += Response;
  24. }
  25.  
  26. public void Response()
  27. {
  28. Console.WriteLine("首场,辛苦了");
  29. }
  30. }
  31.  
  32. class Program
  33. {
  34. static void Main(string[] args)
  35. {
  36. Publisher p = new Publisher();
  37. Subscriber s = new Subscriber(p);
  38. p.DoSomething();
  39. Console.ReadKey();
  40. }
  41. }
  42. }

这就是事件的基本用法,但是事件与委托到底有什么区别呢,从上面的代码可以看出,事件是根据委托来定义的,

  1. public event MessageEventHandler MessageEvent

其实它是利用委托来规定订阅者处理函数的类型(相同的返回类型和参数即为一类),然后可以方便在发布者自身的类中来触发订阅者的一些方法。

但是为什么要事件呢,要实现这些,我仅用委托也可以实现呀,如下代码:

  1. public delegate void MessageEventHandler();
  2. class Publisher
  3. {
  4. public MessageEventHandler MessageEvent;//为了方便,委托名与原来的事件名相同。
  5. // public event MessageEventHandler MessageEvent;
  6. public void DoSomething()
  7. {
  8. Console.WriteLine("等待消息");
  9. Console.WriteLine("首长来啦!!!");
  10. OnMessageEvent();
  11. }
  12. public void OnMessageEvent()
  13. {
  14. if (MessageEvent != null)
  15. {
  16. MessageEvent();
  17. }
  18. }
  19. }
  20. class Subscriber
  21. {
  22. public Subscriber(Publisher p)
  23. {
  24. p.MessageEvent += Response;
  25. }
  26.  
  27. public void Response()
  28. {
  29. Console.WriteLine("首场,辛苦了");
  30. }
  31. }
  32. class Program
  33. {
  34. static void Main(string[] args)
  35. {
  36. Publisher p = new Publisher();
  37. Subscriber s = new Subscriber(p);
  38. p.DoSomething();
  39. Console.ReadKey();
  40. }
  41. }

这样子也同样可以产生相同的结果。

但是当客户端如下调用呢?

  1. Publisher p = new Publisher();
  2. Subscriber s = new Subscriber(p);
  3. p.DoSomething();
  4. p.MessageEvent();
  5. Console.ReadKey();

客户端是不是能随意让发布者产生事件,因此我们可否将发布者的委托定义为private,因为只有发布者的内部才能触发事件嘛,其他人怎么可以?但是这样订阅者就无法订阅了,那我们是否可以增加绑定可解除的函数来订阅此委托呢?

  1. public delegate void MessageEventHandler();
  2. class Publisher
  3. {
  4. private MessageEventHandler MessageEvent;
  5. // public event MessageEventHandler MessageEvent;
  6. public void DoSomething()
  7. {
  8. Console.WriteLine("等待消息");
  9. Console.WriteLine("首长来啦!!!");
  10. OnMessageEvent();
  11. }
  12. public void OnMessageEvent()
  13. {
  14. if (MessageEvent != null)
  15. {
  16. MessageEvent();
  17. }
  18. }
  19. public void Add_MessageEvent(MessageEventHandler m)
  20. {
  21. MessageEvent += m;
  22. }
  23. public void Reomove_MessageEvent(MessageEventHandler m)
  24. {
  25. MessageEvent -= m;
  26. }
  27. }
  28. class Subscriber
  29. {
  30. public Subscriber(Publisher p)
  31. {
  32. //p.MessageEvent += Response;
  33. p.Add_MessageEvent(Response);
  34. }
  35.  
  36. public void Response()
  37. {
  38. Console.WriteLine("首场,辛苦了");
  39. }
  40. }
  41. class Program
  42. {
  43. static void Main(string[] args)
  44. {
  45. Publisher p = new Publisher();
  46. Subscriber s = new Subscriber(p);
  47. p.DoSomething();
  48. Console.ReadKey();
  49. }
  50. }
  51. }

这样就可以实现与事件一样的功能,因此为了方便微软为我们提供了事件访问器,何为事件访问器?

  1. public delegate void MessageEventHandler();
  2. class Publisher
  3. {
  4. private MessageEventHandler MessageEvent;
  5. // public event MessageEventHandler MessageEvent;
  6.  
  7. public event MessageEventHandler TestEvent
  8. {
  9. add
  10. {
  11. lock (MessageEvent)
  12. {
  13. MessageEvent += value;
  14. }
  15. }
  16. remove
  17. {
  18. lock (MessageEvent)
  19. {
  20. MessageEvent -= value;
  21. }
  22.  
  23. }
  24. }
  25. public void DoSomething()
  26. {
  27. Console.WriteLine("等待消息");
  28. Console.WriteLine("首长来啦!!!");
  29. OnMessageEvent();
  30. }
  31. public void OnMessageEvent()
  32. {
  33. if (MessageEvent != null)
  34. {
  35. MessageEvent();
  36. }
  37. }
  38.  
  39. }
  40. class Subscriber
  41. {
  42. public Subscriber(Publisher p)
  43. {
  44. p.TestEvent += Response;
  45.  
  46. }
  47.  
  48. public void Response()
  49. {
  50. Console.WriteLine("首场,辛苦了");
  51. }
  52. }
  53. class Program
  54. {
  55. static void Main(string[] args)
  56. {
  57. Publisher p = new Publisher();
  58. Subscriber s = new Subscriber(p);
  59. p.DoSomething();
  60. Console.ReadKey();
  61. }
  62. }

以上的代码就是利用事件访问器来让委托绑定订阅者的方法,事件访问器中的add和remove能自动编译为+=和-=。

通过reflector,我们可以看到一个事件是如何定义的:

它是申明一个私有的委托:

  1. private MessageEventHandler MessageEvent;

另外利用两个函数来绑定与解除订阅者的方法。

 
 
分类: C#

C#事件与委托的区别的更多相关文章

  1. C# 事件和委托

    相信大家在面试的时候会经常问到事件和委托的区别,为什么.net中需要事件和委托这样类似的问题吧,对于一些初学者来说可平时用的过程中也不知道为什么, 只知道这样用,而对于其中的实现机制不是很清楚, 所以 ...

  2. 事件、委托、委托方法的总结(使用EventHandler<>)

    在C#中,定义事件.委托.委托方法可以使用类库内的EventHandler泛型委托来定义事件.并根据该泛型委托定义实现方法: 同样您也可以自定义委托 来定义事件以及 根据自定义的委托来定义实现事件的方 ...

  3. C#基础精华07(委托事件,委托的使用,匿名方法)

    1.委托概述 委托是一种数据类型,像类一样(可以声明委托类型变量).方法参数可以是int.string.类类型 void M1(int n){  } √ void M2(string s){  } √ ...

  4. [C#参考]事件和委托的关系

    前面说了委托,接下来就要说一说事件了,同时最后再说一下委托和事件的区别. 事件和委托很相似,事件就好像是被简化的针对特殊用途的委托.看下面的图: 从这张图中能看到,事件是发布者的一个成员,它不是类型. ...

  5. C#事件与委托详解【精华 多看看】

    Delegate delegate是C#中的一种类型,它实际上是一个能够持有对某个方法的引用的类.与其它的类不同,delegate类能够拥有一个签名(signature),并且它"只能持有与 ...

  6. C#基础知识之事件和委托

    本文中,我将通过两个范例由浅入深地讲述什么是委托.为什么要使用委托.委托的调用方式.事件的由来..Net Framework中的委托和事件.委托和事件对Observer设计模式的意义,对它们的中间代码 ...

  7. 解密jQuery事件核心 - 委托设计(二)

    第一篇 http://www.cnblogs.com/aaronjs/p/3444874.html 从上章就能得出几个信息: 事件信息都存储在数据缓存中 对于没有特殊事件特有监听方法和普通事件都用ad ...

  8. c#事件与委托

    C#.net 目录(?)[-] 将方法作为方法的参数 将方法绑定到委托 事件的由来 事件和委托的编译代码 委托事件与Observer设计模式 范例说明 Observer设计模式简介 实现范例的Obse ...

  9. 《C#高级编程》学习笔记------C#中的事件和委托

    本文转载自张子阳 目录 委托的作用 将方法绑定到委托 事件的来由 Observer设计模式 .Net Framework中的委托与事件   引言 委托 和 事件在 .Net Framework中的应用 ...

随机推荐

  1. 讨论oracle在rowid和rownum

    [ 概要 ] 刚刚接触oracle的同学可能经常会被rowid和rownum这两个词弄混, 弄清楚这两个家伙对于我们写sql会有非常大的帮助, 以下偶就抛砖引玉, 简单地谈谈他们之间的差别吧. [ 比 ...

  2. java一般使用基础

    1.这是一个通用 仿制药javaA型安全机制来保护. 它是通过变量的类型,如果,实现变量类型限制,从而保证了程序编译变量类型的安全性在一定程度上.反之.如果没有泛型,这些只存在于程序,如果猿的大脑,这 ...

  3. 杭电1162Eddy&#39;s picture

    Eddy's picture Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Tota ...

  4. linux_安装 redis

    Installation Download, extract and compile Redis with: $ wget http://download.redis.io/releases/redi ...

  5. ArcGIS网络分析之Silverlight客户端最近设施点分析(四)

    原文:ArcGIS网络分析之Silverlight客户端最近设施点分析(四) 在上一篇中说了如何实现最近路径分析,本篇将讨论如何实现最近设施点分析. 最近设施点分析实际上和路径分析有些相识,实现的过程 ...

  6. MySQL检查连接的最大数量和改变的最大连接数

    版权声明:本文博主原创文章.博客,未经同意不得转载.

  7. Swift语言指南(八)--语言基础之元组

    原文:Swift语言指南(八)--语言基础之元组 元组 元组(Tuples)将多个值组合为一个复合值.元组内的值可以是任何类型,各个元素不需要为相同类型(各个元素之间类型独立,互不干扰--Joe.Hu ...

  8. 为什么使用Hystrix?

    分布式服务弹性框架“Hystrix”实践与源码研究(一)   文章初衷 为了应对将来在线(特别是无线端)业务量的成倍增长,后端服务的分布式化程度需要不断提高,对于服务的延迟和容错管理将面临更大挑战,公 ...

  9. 合并多段zip文件并解压缩

    cat xxx.zip.*** >xxx.zip unzip xxx.zip

  10. iOS 学习

    iOS 学习资料 (适合初学者) 本文资料来源于GitHub 一.视频教程(英文) Developing iOS 7 Apps for iPhone and iPad斯坦福开放教程之一, 课程主要讲解 ...