艾伟_转载:解惑答疑:C#委托和事件

  相信很多人一直为C#委托和事件所困惑,尤其是C#的初学者,学到这一部分会感觉比较困难,很有可能就放弃了,而且.NET对委托和事件封装得挺好,一般都不怎么用到自定义的委托和事件,所以放弃学习该技术就有了借口!

  网上也有不少此类的文章,最具代表性的是张子阳的C#中的委托和事件这篇,写得的确很好,得到很多读者的赞赏,但我
看评论,还是发现了些问题,因为有不少读者是看了一遍又一遍,每次感觉都蛮好,可是隔一段时间,对“委托和事件”又迷糊了,于是又来看!我真搞不懂,为什
么会出现这种情况!后来想想,文章虽好,但总结的地方没有把重点列出来;再者,读者跟着作者的思路,的确能把文章看懂,但是读者自己不得要领,没有真正弄
明白,因此就出现了上面提到的状况!

  C#委托和事件真的难吗,其实不然。要搞懂它,第一,要看你的理解能力;第二,要看你怎么理解它。如果你觉得理解起来比较困难,那我们可以换种理解方式,也许能很好地理解它了!其实委托和事件的确不难,大牛级别的甚至都不屑写此类文章!

  为什么会有委托?

  委托其实就是个方法指针,拥有同样参数和返回值的任何方法都能传给委托;委托能够消除条件分支语句,不需要根据if、case这些语句来判断具体调用哪个方法!而委托又是从观察者模式演化而来,这里推荐阅读TerryLee的这篇观察者模式文章。  

  前面说的的就算不理解也不要紧,关键是理解方法、委托、事件之间的关系。可以这样说,方法是“委托”给委托的,而委托是“委托”给事件的。可以将事件看成是委托的一个容器,里面可以加一连串的委托!这样来理解,那所有的事情就都解决了!

  当然,我们都是在某个方法中触发事件,事件将其交给委托,委托再交给方法,方法再进行实际的操作,与上面的步骤刚好相反!其实触发事件的目的就是触发具体方法!

  再来说说委托的好处(上面没举例子),比如你开发了一个电子商务平台,后台有管理商品的功能,而商品信息有七八列或者更多,包括编号、商品名称、价
格、上架时间等等,该信息又能根据任意一列来进行排序!如果没有委托,我们将根据点击某列所产生的信息,将这信息传给某个排序方法,而这个排序方法会接受
传来的信息作为参数,再根据内部的分支语句if、case等来判断具体采用哪个排序方法,这样的话,逻辑变复杂,这过程当中还要做很多无用功(因为很有可
能要进行多次判断才能找到要真正执行的方法),而且如果我们将来再增加列,又得增加分支语句,违背了“开放—封闭”原则,维护起来比较麻烦!有了委托,我
们不需要传递任何参数,直接将具体方法传给委托即可,增加列则只要增加一个新方法,爽!我们完全可以通过委托来调用方法,那为什么还要事件呢?事件其实是
对委托进行一种限制,使其无法使用“=”赋值运算符(如果使用则在编译时产生错误),只能使用“+=”或者“-=”运算符,这就防止了程序员误将原先的委
托链给覆盖掉,另外delegate类从MulticastDelegate(多路广播委托)继承而来,所以可以将多个委托赋给同一个事件!

  最后,列一串代码把上面的概念理清一下

class Program{static void Main(string[] args)    {       XiaoBai xiaobai = new XiaoBai();//Google公司        ItCompany google = new ItCompany("谷歌中国", "CTO", xiaobai);//微软公司        ItCompany microsoft = new ItCompany("微软中国", "架构师", xiaobai);//花旗银行    FinanceCompany AmericaBank = new FinanceCompany("花旗银行", "金融分析师", xiaobai);//委托的好处,可以应用于不同的类的不同方法//方法“委托”给委托,委托“委托”给事件//委托类型与事件声明时的委托类型相同//因为是传引用,所以方法后面不能带括号,带括号则是调用方法了//一个委托可以搭载多个方法,一个事件则拥有一个委托链        xiaobai.Update += new TheEventHandler(google.ComeToItCompany);        xiaobai.Update += new TheEventHandler(microsoft.ComeToItCompany);        xiaobai.Update += new TheEventHandler(AmericaBank.ComeToFinanceCompany);        xiaobai.SubjectState = "我小白过来应聘职位啦!";//发出通知,触发事件        xiaobai.Notify();//以下代码与上面相似        XiaoHua xiaohua = new XiaoHua();        ItCompany microsoft2 = new ItCompany("微软总公司", "CEO", xiaohua);    FinanceCompany ChinaBank = new FinanceCompany("中国央行", "财务部总经理", xiaohua);        xiaohua.Update += new TheEventHandler(microsoft2.ComeToItCompany);        xiaohua.Update += new TheEventHandler(ChinaBank.ComeToFinanceCompany);        xiaohua.SubjectState = "我小华过来应聘职位啦!";        xiaohua.Notify()        Console.ReadLine();    }}//通知者接口interface Subject{void Notify();

string SubjectState    {get;set;    }} //事件处理程序的委托,相当于一个类(在编译成IL后确确实实是类)或者方法指针,与常规类定义不同,带参数和返回值    delegate void TheEventHandler();//小白class XiaoBai : Subject{//声明一事件Update,类型为委托TheEventHandler    public event TheEventHandler Update;private string action; //用Notify方法触发事件    public void Notify()    {        Update();    }public string SubjectState    {get { return action; }set { action = value; }    }}//小华class XiaoHua : Subject{//声明一事件Update,类型为委托TheEventHandler    public event TheEventHandler Update;private string action;//用Notify方法触发事件    public void Notify()    {        Update();    }public string SubjectState    {get { return action; }set { action = value; }    }}//IT行业class ItCompany{private string companyname;private string job;private Subject sub;

public ItCompany(string _companyname, string _job, Subject _sub)    {        companyname = _companyname;        job = _job;        sub = _sub;    }//参数和返回值与委托TheEventHandler一致    public void ComeToItCompany()    {        Console.WriteLine("{0} {1}: 来我们公司做{2}!", sub.SubjectState, companyname, job);    }}//金融行业class FinanceCompany{private string companyname;private string job;private Subject sub;

public FinanceCompany(string _companyname, string _job, Subject _sub)    {        companyname = _companyname;        job = _job;        sub = _sub;    }//参数和返回值与委托TheEventHandler一致    public void ComeToFinanceCompany()    {        Console.WriteLine("{0} {1}: 来我们公司做{2}!", sub.SubjectState, companyname, job);    }}

 

  通过以上总结,我相信大家对C#委托和事件应该可以更好地理解了!当然,委托的知识不止这些,还会用到检查空值、异常处理和多线程处理等等,这篇文章仅在
解惑(我也不高兴浪费太多的时间来具体讲解)!如果你想更好地掌握委托和事件,可以看下上面提到的张子阳的两篇文章或者买本《C#本质论》仔细研读;如果
你想了解观察者模式,可以看下上面提到的TerryLee那篇文章;如果你还没有学习设计模式或者刚刚开始学习,我建议阅读《大话设计模式》;如果你学习
设计模式有一段时间了,我建议阅读《设计模式:基于C#的工程化实现及扩展》!祝各位程序员好运!

时间: 2024-08-22 14:23:09

艾伟_转载:解惑答疑:C#委托和事件的相关文章

艾伟_转载:一个.NET委托的故事:彼得,老板和宇宙

紧耦合 从前,在南方一块奇异的土地上,有个工人名叫彼得,他非常勤奋,对他的老板总是百依百顺.但是他的老板是个吝啬的人,从不信任别人,坚决要求随时知道彼得的工作进度,以防止他偷懒.但是彼得又不想让老板呆在他的办公室里站在背后盯着他,于是就对老板做出承诺:无论何时,只要我的工作取得了一点进展我都会及时让你知道.彼得通过周期性地使用"带类型的引用"(原文为:"typed reference" 也就是delegate??)"回调"他的老板来实现他的承诺,

艾伟_转载:把委托说透(1):开始委托之旅 委托与接口

委托,本是一个非常基础的.NET概念,但前一阵子在园子里却引起轩然大波.先是Michael Tao的随笔让人们将委托的写法与茴香豆联系到了一起,接着老赵又用一系列文章分析委托写法的演变,并告诫"嘲笑孔乙己的朋友们,你们在一味鄙视"茴"的四种写法的同时,说不定也失去了一个了解中国传统文化的机会呢!". 在我个人看来,委托是.NET Framework中一个非常炫的特性,绝不会向有些评论里说的那样,根本没有机会接触.恰恰相反,我们几乎每天都会接触委托,使用委托. 其实园

艾伟_转载:把委托说透(2):深入理解委托

在上一篇随笔中我们通过示例逐步引入了委托,并比较了委托和接口.本文将重点剖析委托的实质. 委托在本质上仍然是一个类,我们用delegate关键字声明的所有委托都继承自System.MulticastDelegate.后者又是继承自System.Delegate类,System.Delegate类则继承自System.Object.委托既然是一个类,那么它就可以被定义在任何地方,即可以定义在类的内部,也可以定义在类的外部. 正如很多资料上所说的,委托是一种类型安全的函数回调机制, 它不仅能够调用实

艾伟_转载:把委托说透(4):委托与设计模式

委托与很多设计模式都有着千丝万缕的联系,在前面的随笔中已经介绍了委托与策略模式的联系,本节主要来讨论委托与其他两个模式:观察者模式和模板方法模式. 委托与观察者模式 在.NET中,很多设计模式得到了广泛应用,如foreach关键字实现了迭代器模式.同样的,.NET中也内置了观察者模式的实现方式,这种方式就是委托. 观察者模式的一般实现 网上可以找到很多资料介绍观察者模式的实现,我这里介绍一种简单的退化后的观察者模式,即Subject类为具体类,在其之上不再进行抽象. public class S

艾伟_转载:把委托说透(3):委托与事件

在把委托说透(1)和(2)中,先后介绍了委托的语法和本质,本文重点介绍.NET中与委托息息相关的概念--事件.在此之前,首先需要补充(2)中遗漏的一部分内容,即C#在语法上对委托链的支持. C#编译器为委托类型提供了+=和-=两个操作符的重载,分别对应Delegate.Combine和Delegate.Remove方法,使用这两个操作符可以大大简化委托链的构造和移除. 好了,有了+=和-=,我们就可以开始今天的话题了. 什么是事件? 事件(event)是类型中的一种成员,定义了事件成员的类型允许

艾伟_转载:C# 委托的同步调用和异步调用

委托的Invoke方法用来进行同步调用.同步调用也可以叫阻塞调用,它将阻塞当前线程,然后执行调用,调用完毕后再继续向下进行. 同步调用的例子: using System;using System.Threading;public delegate int AddHandler(int a, int b);public class Foo {static void Main() { Console.WriteLine("**********SyncInvokeTest**************&

艾伟_转载:.NET委托:一个C#睡前故事

英文版原作者:Chris Sells(www.sellsbrothers.com) 翻译:袁晓辉(www.farproc.com http://blog.csdn.net/uoyevoli) 原文地址: http://dev.csdn.net/article/82/82644.shtm 紧耦合 从前,在南方一块奇异的土地上,有个工人名叫彼得,他非常勤奋,对他的老板总是百依百顺.但是他的老板是个吝啬的人,从不信任别人,坚决要求随时知道彼得的工作进度,以防止他偷懒.但是彼得又不想让老板呆在他的办公室

艾伟_转载:数组排序方法的性能比较(上):注意事项及试验

昨天有朋友写了一篇文章,其中比较了List的Sort方法与LINQ中排序方法的性能,而最终得到的结果是"LINQ排序方法性能高于List.Sort方法".这个结果不禁让我很疑惑.因为List.Sort方法是改变容器内部元素的顺序,而LINQ排序后得到的是一个新的序列.假如两个排序方法的算法完全一致,LINQ排序也比对方多出元素复制的开销,为什么性能反而会高?如果LINQ排序的算法/实现更为优秀,那为什么.NET Fx不将List.Sort也一并优化一下呢?于是今天我也对这个问题进行了简

艾伟_转载:老赵谈IL(3):IL可以看到的东西,其实大都也可以用C#来发现

在上一篇文章中,我们通过一些示例谈论了IL与CLR中的一些特性.IL与C#等高级语言的作用类似,主要用于表示程序的逻辑.由于它同样了解太多CLR中的高级特性,因此它在大部分情况下依旧无法展现出比那些高级语言更多的CLR细节.因此,如果您想要通过学习IL来了解CLR,那么这个过程很可能会"事倍功半".因此,从这个角度来说,老赵并不倾向于学习IL.不过严格说来,即使IL无法看出CLR的细节,也不足以说明"IL无用"--这里说"无用"自然有些夸张.但是