读书人

对《顿悟?新手浅谈事件与委托》一文中

发布时间: 2012-06-14 16:00:31 作者: rapoo

对《顿悟?!新手浅谈事件与委托》一文中的代码改进
原文请点击:《顿悟?!新手浅谈事件与委托》
首先,委托是在事件发生前就应该定下的计划,一旦事件发生,就开始执行委托好的事情。
这里事先做好委托计划,打电话的话就是让漂亮执行Doit方法帮收衣服。
在这里,“我”每天在那等啊等,Check天气来Check天气去,总算下雨了,赶紧打电话约漂亮MM……啊!不是,赶紧打电话让漂亮MM帮收衣服……
理解得不对的话,轻喷o(□)o

C# code
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帮我收衣服了!


另外做了一个新例子,但愿新人没误导新人……
C# code
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\\ 按任意键退出: 



[解决办法]
C# code
/// <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、委托,就是被触发的事件由谁来执行。委托,顾名思义,也就是叫其他人来执行。

如果你能抓住这两点,那么在建立软件模型中就会自然而然的去用委托和事件。
[解决办法]
探讨

真正的委托应该这样用,注意箭头内的那段代码,多个情敌向漂亮MM提出委托的要求那里。
C# code

using System;
namespace 收衣服
{

/// <summary>
/// 天气情况枚举
/// </summary>
public enum EnmWeather
{
Rainy,
Sunny
……

[解决办法]
C# code
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部 使用的...

读书人网 >C#

热点推荐