对《顿悟?!新手浅谈事件与委托》一文中的代码改进
原文请点击:《顿悟?!新手浅谈事件与委托》
首先,委托是在事件发生前就应该定下的计划,一旦事件发生,就开始执行委托好的事情。
这里事先做好委托计划,打电话的话就是让漂亮执行Doit方法帮收衣服。
在这里,“我”每天在那等啊等,Check天气来Check天气去,总算下雨了,赶紧打电话约漂亮MM……啊!不是,赶紧打电话让漂亮MM帮收衣服……
理解得不对的话,轻喷o(╯□╰)o
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace 收衣服{ /// <summary> /// 先定义一个委托 /// </summary> public delegate void Mydelegate(); /// <summary> /// 我 /// </summary> class me { /// <summary> /// 打电话求助事件 /// </summary> public event Mydelegate Call; /// <summary> /// 让我来看一下天气怎么样 /// </summary> /// <param name="weather">天气</param> public void CheckWeather(string weather) { if (weather == "雨")// 下雨?还不赶紧打电话给漂亮MM!!! { Call(); } else { Console.WriteLine("没下雨?!唉,还是找别的理由打电话给漂亮MM吧……"); } } } /// <summary> /// 邻居 /// </summary> class Neighbor { /// <summary> /// 邻居还要有一个能处理事件的方法 /// </summary> public void Doit() { Console.WriteLine("漂亮MM帮我收衣服了!"); } } class Program { static void Main(string[] args) { me me = new me(); //实例化一个我 Neighbor PLMM = new Neighbor(); //假设邻居是一个漂亮MM~ me.Call += new Mydelegate(PLMM.Doit);// 先定好打电话是要让漂亮执行Doit方法帮收衣服 int i = 0; string weather = "晴"; while (i < 10) { if (i++ % 3 == 0)// 虚拟一个下雨的条件 { weather = "雨"; Console.Write("下雨了!!!"); } else { weather = "晴"; } me.CheckWeather(weather); } Console.ReadKey(); } }}// 执行结果:// 下雨了!!!漂亮MM帮我收衣服了!// 没下雨?!唉,还是找别的理由打电话给漂亮MM吧……// 没下雨?!唉,还是找别的理由打电话给漂亮MM吧……// 下雨了!!!漂亮MM帮我收衣服了!// 没下雨?!唉,还是找别的理由打电话给漂亮MM吧……// 没下雨?!唉,还是找别的理由打电话给漂亮MM吧……// 下雨了!!!漂亮MM帮我收衣服了!// 没下雨?!唉,还是找别的理由打电话给漂亮MM吧……// 没下雨?!唉,还是找别的理由打电话给漂亮MM吧……// 下雨了!!!漂亮MM帮我收衣服了!
using System;namespace 收衣服{ /// <summary> /// 包含事件相关参数的类 /// </summary> public class MyEventArgs { private Person offerHelpPerson; /// <summary> /// 提供服务的人 /// </summary> public Person OfferHelpPerson { get { return offerHelpPerson; } set { offerHelpPerson = value; } } private Person needHelpPerson; /// <summary> /// 需要服务的人 /// </summary> public Person NeedHelpPerson { get { return needHelpPerson; } set { needHelpPerson = value; } } private EnmWeather weather; /// <summary> /// 天气情况 /// </summary> public EnmWeather Weather { get { return weather; } set { weather = value; } } /// <summary> /// 构造方法 /// </summary> /// <param name="offerHelpPerson">提供服务的人</param> /// <param name="needHelpPerson">需要服务的人</param> /// <param name="weather">天气情况</param> public MyEventArgs(Person offerHelpPerson, Person needHelpPerson, EnmWeather weather) { this.offerHelpPerson = offerHelpPerson; this.needHelpPerson = needHelpPerson; this.weather = weather; } } /// <summary> /// 天气情况枚举 /// </summary> public enum EnmWeather { Rainy, Sunny } /// <summary> /// 定义一个委托 /// </summary> /// <param name="args">相关参数</param> public delegate void WeatherHandller(MyEventArgs args); /// <summary> /// 人 /// </summary> public class Person { private string name; public string Name { get { return name; } } public Person(string name) { this.name = name; } /// <summary> /// 下雨事件 /// </summary> public event WeatherHandller OnWeatherIsRainy; /// <summary> /// 查看天气情况 /// </summary> /// <param name="args">相关参数</param> public void CheckWeather(MyEventArgs args) { // 可以帮收衣服的人开始监听天气 this.OnWeatherIsRainy(args); } } class Program { /// <summary> /// 当天的天气情况 /// </summary> public static EnmWeather weather; static void Main(string[] args) { Person me = new Person("我");// new一个“我”出来 Person plmm = new Person("漂亮MM");// new一个“漂亮MM”出来 plmm.OnWeatherIsRainy += new WeatherHandller(plmm_OnWeatherIsRainy); // 漂亮MM接收到一个帮收衣服的委托 int i = 0; Console.WriteLine("执行结果:"); while (i < 10) { if (i++ % 3 == 0)// 虚拟一个下雨的条件 { weather = EnmWeather.Rainy;// 下雨啦 } else { weather = EnmWeather.Sunny;// 不下雨那就放晴吧o(╯□╰)o } Console.Write("现在是{0}号:", i); // 漂亮MM查看当天的天气情况 plmm.CheckWeather(new MyEventArgs(plmm, me, weather)); } Console.WriteLine("按任意键退出:"); Console.ReadKey(); } /// <summary> /// 定义一个帮收衣服的方法 /// </summary> /// <param name="args">相关参数</param> static void plmm_OnWeatherIsRainy(MyEventArgs args) { if (args.Weather == EnmWeather.Rainy) { Console.WriteLine("今天是【{0}】,【{1}】要帮【{2}】收衣服 o(╯□╰)o ", "雨天", args.OfferHelpPerson.Name, args.NeedHelpPerson.Name); } else { Console.WriteLine("今天是【{0}】,【{1}】不用帮【{2}】收衣服 ~O(∩_∩)O~", "晴天", args.OfferHelpPerson.Name, args.NeedHelpPerson.Name); } } }}\\ 执行结果:\\ 现在是1号:今天是【雨天】,【漂亮MM】要帮【我】收衣服 o(╯□╰)o\\ 现在是2号:今天是【晴天】,【漂亮MM】不用帮【我】收衣服 ~O(∩_∩)O~\\ 现在是3号:今天是【晴天】,【漂亮MM】不用帮【我】收衣服 ~O(∩_∩)O~\\ 现在是4号:今天是【雨天】,【漂亮MM】要帮【我】收衣服 o(╯□╰)o\\ 现在是5号:今天是【晴天】,【漂亮MM】不用帮【我】收衣服 ~O(∩_∩)O~\\ 现在是6号:今天是【晴天】,【漂亮MM】不用帮【我】收衣服 ~O(∩_∩)O~\\ 现在是7号:今天是【雨天】,【漂亮MM】要帮【我】收衣服 o(╯□╰)o\\ 现在是8号:今天是【晴天】,【漂亮MM】不用帮【我】收衣服 ~O(∩_∩)O~\\ 现在是9号:今天是【晴天】,【漂亮MM】不用帮【我】收衣服 ~O(∩_∩)O~\\ 现在是10号:今天是【雨天】,【漂亮MM】要帮【我】收衣服 o(╯□╰)o\\ 按任意键退出:
/// <summary> /// 查看天气情况 /// </summary> /// <param name="args">相关参数</param> public void CheckWeather(MyEventArgs args) { // 可以帮收衣服的人开始监听天气 //this.OnWeatherIsRainy(args); [color=#FF0000] if(this.OnWeatherIsRainy!=null) { this.OnWeatherIsRainy(args); }[/color] }
[解决办法]
我重复下我说的话,掌握委托,知道在什么地方正确的使用,是合格的C#程序员起码的标准。
如果你没有意识到委托的普遍作用,不是收考卷就是收衣服,要不然就是什么猫叫狗叫,恰恰说明你没怎么理解。如果我是老师,我根本不会向学生举这种毫无意义的例子。
[解决办法]
委托和事件只要抓住两点最基本的原则:
1、事件有个诱因,也就是谁来触发以及触发的条件。
2、委托,就是被触发的事件由谁来执行。委托,顾名思义,也就是叫其他人来执行。
如果你能抓住这两点,那么在建立软件模型中就会自然而然的去用委托和事件。
[解决办法]
using System;using System.Linq;namespace RainAndCallMM{ public delegate void Mydelegate(); //先定义一个委托类 class me //我 { public event Mydelegate CallNeighbor; public void NotifyNeighbor() //邻居MM们告诉我如何通知她我就如何通知她 { if (CallNeighbor != null) //她跟我说了我才去通知,如果有1000个MM,我就通知1000个 { CallNeighbor(); } } public void Rain() { Console.WriteLine("下雨了"); NotifyNeighbor(); } } class Neighbor //邻居 { public me m; public Neighbor(me m) { this.m = m; GreetMe(); //构造函数订阅事件 } public void GreetMe() //先跟说帅锅下雨要跟我打招呼 { m.CallNeighbor += TellMe; } public void TellMe() //帅锅通知我了 { Console.WriteLine("哦,隔壁的帅锅来提醒我收衣服了。"); } } class Program { static void Main(string[] args) { me m = new me(); //帅锅 Neighbor n1 = new Neighbor(m); Neighbor n2 = new Neighbor(m); m.Rain(); Console.ReadKey(); } }}
[解决办法]
委托有一个比较恰当的应用场景我说一下:
当你编码的DLL模块 需要去调用还不存在(还未被开发出来的)方法的时候我们可以使用委托来实现这个
比如你开发了一个底层socket通信模块. 他的基本逻辑是:如果某端口产生了一个socket消息,那么你将把这个消息通知给 业务逻辑层.
这个时候业务逻辑的需求都未定呢, 你怎么开发呢? 所以你想到了使用委托.
比如你开发完的这个DLL就叫做 socket.dll 那么好了.
接下来... 你可以把这个DLL提供给 研发1部使用. 他们的某个程序内需要使用socket通信. 于是他们在设计完了业务逻辑之后调用你的dll,实现一个委托方法.完成了sokcet消息的接收 一切搞定.
然后过了几天, 你又把这个DLL提供给研发2部使用.........
-------------------------
于是, 你联想到了什么?
你想起来没, C#的button控件不就是这样吗 button 让你实现他的 button 事件. 他为什么会这么设计?
因为他的设计符合我上面的原则:
1,为了提供给后续的开发者使用,而他自己只实现了最基本的逻辑功能
2,他的逻辑是: 把操作系统的鼠标事件透传给业务层,而我的举例是socket.dll把soeckt消息透传给业务层
3,都是为了给将来的 研发1部... 研发2部 使用的...