喜羊羊与灰太狼之委托与事件

        记得我在初学.NET的时候对委托和事件这对概念理解的是很模糊的,当时在看书的时候只能理解书中代码的逻辑,知道委托和事件怎样用代码具体实现,但对其中的原理理解甚少。这几天在学习ASP.NET网页编程的时候,里面又多次提到了事件、事件参数。于是我决定再重新理解一次委托和事件

       为了形象的描述委托和事件实现的过程,我想到了“喜羊羊和灰太狼”的故事。我比较爱看动画片,尤其是爱看像《喜羊羊与灰太狼》、《蜡笔小新》等这样既搞笑又弱智的动画片。没看过《喜羊羊与灰太狼》的可以趁此机会看一下。

为了描述这个故事,我们首先需要建立两个类:Goat和Wolf
//狼类的代码
public class Wolf
    {
        string name;    //定义一个变量用于存储狼的姓名
        //构造函数
        public Wolf(string name)
        {
            this.name = name;
        }
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
      
        public void Scare()    //狼有一个恐吓的方法
        {
            Console.WriteLine("哈哈,我是{0},小肥羊们快跟我回狼堡吧!",name );
            Console.WriteLine(); 
        }
    }
//山羊类的代码
public class Goat
    {
        string name;    //定义一个变量用于存储山羊的名字
        
        //构造函数
        public Goat(string name)
        {
            this.name = name;
 
        }
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        public void Run()    //羊有一个逃跑的方法
        {
            Console.WriteLine("狼来啦,{0}快跑!" ,name); 
            Console.WriteLine();
        }
    }


       在动画片里,灰太狼每次看到小羊的时候都是先和小羊聊天、说一些吓唬小羊的话,然后再上去抓羊,这时候喜羊羊早就想出逃脱的办法了,怪不得每次灰太狼都抓不到羊,看到羊先和他们扯淡,然后才行动。

       不说废话了,下面我给大家讲怎样用委托和事件实现:狼吓唬小羊,小羊听到后撒腿就跑。

       首先我们要明白一个常识:灰太狼再笨也不会自己告诉小羊说我来了,你们快跑吧。所以在Wolf类当中不可以出现Goat类的对象,也就是说不可以把小羊的Run方法写在狼的Scare方法中。Wolf和Goat双方不能关联,那就要通过委托来解决这个问题

       委托其实就是对方法的引用,一旦为委托分配了方法,那么委托就可以像方法一样使用。委托定义了对方法特征的抽象,委托和函数一样可以有参数和返回值,为委托分配的方法的格式要和委托一致,即方法的参数和返回值要和委托一样。委托可以看做是函数的“类”,为委托分配的函数就是委托的实例。

首先我们定义一个委托
public delegate void WolfScareEventHandler();    

       定义一个没有参数和返回值的委托,委托的名字是WolfScareEventHandler,委托用关键字delegate声明,可以放在Wolf类的里面,也可以放在类外面,因为委托本身也是一种“特殊的类”

然后我们定义一个WolfScareEventHandler委托类型的事件WolfScare
public event WolfScareEventHandler WolfScare;



       事件用Event关键字声明,事件要声明在Wolf类的内部,因为这个事件是属于Wolf类的(我们通常说类有三要素:属性、事件、方法)

包含WolfScare事件的Wolf类代码
public class Wolf
    {
        string name;
        //构造函数
        public Wolf(string name)
        {
            this.name = name;
        }
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        //声明一个WolfScareEventHandler委托类型的事件
        public event WolfScareEventHandler WolfScare;
        public void Scare()
        {
            Console.WriteLine("哈哈,我是{0},小肥羊们快跟我回狼堡吧!",name );
            //下面是触发WolfScare事件的代码
            if (WolfScare != null)
            {
                WolfScare();
            }
        }
    }


这样Wolf类就具有了事件,而且在狼执行Scare方法时事件会被触发,如果为事件分配了方法,那么将执行方法。

最关键的是要看主程序的代码:
static void Main(string[] args)
        {
            Wolf bigWolf = new Wolf("灰太狼");        //声明一个Wolf类的对象bigWolf,名字是“灰太狼”
            
            //声明三个Goat对象
            Goat happyGoat = new Goat("喜羊羊");
            Goat lazyGoat = new Goat("懒羊羊");
            Goat strongGoat = new Goat("沸羊羊");
            //给事件分配方法
            bigWolf.WolfScare += new WolfScareEventHandler(happyGoat .Run );
            bigWolf.WolfScare += new WolfScareEventHandler(lazyGoat.Run);
            bigWolf.WolfScare += new WolfScareEventHandler(strongGoat.Run);
            bigWolf.Scare ();
        }



      在主程序当中,为bigWolf对象的事件WolfScare分配了三个方法:happyGoat .Run 、lazyGoat.Run、strongGoat.Run。用委托的好处就在这里,不用在Wolf类当中出现Goat类,而是在主程序当中为事件动态分配方法,而且这些方法可以是不同对象的方法,只要格式和委托类型一致就可以了。

      这样在bigWolf执行Scare方法时,事件WolfScare会被触发,同时执行happyGoat .Run 、lazyGoat.Run、strongGoat.Run三个方法,运行结果如下




有人会说.NET中控件事件过程一般都是带参数的,像下面这样:
protected void Button1_Click(object sender, EventArgs e)
        {
            
        }


        这个事件过程带两个参数sender和e,分别是object类型和EventArgs类型的。sender是指此事件是在哪个对象中被触发的,在这里就是Button1;e是一个事件参数,里面携带着一些与此事件相关的数据

那么我们对“喜羊羊和灰太狼”的代码进行改造,让它的事件也带参数

先定义一个事件参数类WolfScareEventArgs,让它继承EventArgs类
public class WolfScareEventArgs
    {
        string name;        //定义一个name变量,让它存储狼的名字,这样事件参数就可以携带狼的名字了
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
    }


对委托改造:事件过程(即为委托分配的方法)是带参数的,那么委托也要带参数
public delegate void WolfScareEventHandler(object sender,WolfScareEventArgs e);


改造后的Wolf类
public class Wolf
    {
        string name;
        //构造函数
        public Wolf(string name)
        {
            this.name = name;
        }
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        //声明一个WolfScareEventHandler委托类型的事件
        public event WolfScareEventHandler WolfScare;
        public void Scare()
        {
            Console.WriteLine("哈哈,我是{0},小肥羊们快跟我回狼堡吧!",name );
            Console.WriteLine();
            //下面是触发WolfScare事件的代码
            if (WolfScare != null)
            {
                //定义一个事件参数对象
                WolfScareEventArgs args = new WolfScareEventArgs();
                args.Name = this.name;        //将狼的名字赋给事件参数的Name属性
                WolfScare(this,args );
                
            }
        //重写ToString方法,这样sender.tostring()就可以显示狼的名字了
        public override string ToString()
        {
            return this .name ;
        }
    }


Goat类的代码也要进行改造:
public class Goat
    {
        string name;
        
        //构造函数
        public Goat(string name)
        {
            this.name = name;
 
        }
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        public void Run(object sender,WolfScareEventArgs e)
        {
            Console.WriteLine("{0}来啦,{1}快跑!",e.Name ,name);     //在这里可以用参数e的Name属性显示出哪只狼来了
            Console.WriteLine("追我的狼是:"+sender.ToString ());     //这里可以用sender对象的ToString方法显示出触发事件的狼的名字
            Console.WriteLine();
        }
    }


主程序基本不用变,为了方便演示,我们把狼的名字改为“红太狼”
static void Main(string[] args)
        {
            Wolf bigWolf = new Wolf("红太狼");
            Goat happyGoat = new Goat("喜羊羊");
            Goat lazyGoat = new Goat("懒羊羊");
            Goat strongGoat = new Goat("沸羊羊");
            //给事件添加方法
            bigWolf.WolfScare += new WolfScareEventHandler(happyGoat .Run );
            bigWolf.WolfScare += new WolfScareEventHandler(lazyGoat.Run);
            bigWolf.WolfScare += new WolfScareEventHandler(strongGoat.Run);
            bigWolf.Scare ();
        }



程序运行的效果:





讲到这里可能有很多人还是觉得上面讲的事件和.NET中的控件事件不太一样,其实他们的原理是一样的:

当我们双击某个控件时,代码编辑器会自动为我们编写好一个事件处理过程
protected void Button1_Click(object sender, EventArgs e)
        {
            
        }


       其实这里的Button1_Click 就类似于上面讲到的Goat类的Run方法。Button1_Click过程的背后是事件Button1.Click,它类似于上面的bigWolf.WolfScare事件。
      其实Button1_Click可以是随便的一个名字,比如  fun (object sender, EventArgs e),只要你在代码中添加如下语句:
Button1.Click+=New EventHandler(fun);

       这样当Button1的Click事件被触发时,就会执行fun方法。你可以为Button1.Click事件分配任意多的方法,当事件被触发时,这些方法都会被执行。

       你看到的事件过程都是类似于 protected void Button1_Click(object sender, EventArgs e)这样的,这是因为:当你双击某个控件时,系统自动创建过程protected void Button1_Click(object sender, EventArgs e),并将它分配给事件Button1.Click. 你也可以把其它控件的事件过程分配给事件Button1.Click,如:
protected void TextBox1_TextChanged(object sender, EventArgs e)
        {
                Response.Write("这是文本框的事件过程");
        }
Button1.Click+=New EventHandler(TextBox1_TextChanged)


       这样单击Button1,TextBox1_TextChanged事件过程也会被执行。
       总之事件过程和一般的函数和方法是一样的,只不过系统把它分配给了事件,当事件触发时,执行被分配的事件过程


事件的原理你明白了吗?


  • 20
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 36
    评论
### 回答1: 好的,我会用中文写一篇以喜羊羊为主角的同人文。 喜羊羊生活在一个美丽的草原上。喜羊羊是一只快乐的小绵羊,总是带着灿烂的笑容,唱着歌,跳着舞。则是一只凶狠的,他总是试图抓住喜羊羊,但是从来没有成功过。 有一天,喜羊羊被困在了一个悬崖上,无法自救。看到了这一幕,他虽然很想吃掉喜羊羊,但是他也不忍心看到喜羊羊受到伤害。于是,决定救喜羊羊。 他越过了悬崖,把喜羊羊从危险的地方救了出来。喜羊羊很感激,并且开始理解他,他不再把当作敌人,而是看作朋友。 从那天起,喜羊羊开始了一段有趣的友谊。他们一起玩耍,一起冒险,一起生活在这个美丽的草原上。也不再试图吃掉喜羊羊,而是保护喜羊羊,让他快乐。 这就是一篇以喜羊羊为主角的同人文,说明了友谊可以 ### 回答2: 喜羊羊是一对著名的动画角色,他们之间的关系既是互相争斗,又充满了互相关心与帮助。在这篇同人文中,我将描述一个关于他们团结合作的故事。 一天,美丽的阳光洒满草原,喜羊羊都正在自己的领地上玩耍。突然,一只凶猛的野出现在草原上,吓得其他小动物们四处逃散。喜羊羊立即意识到这并不是普通的野,而是一个来自外地的入侵者。 见状,想要去对付野,但喜羊羊却拦住了他。他说:“我们要团结起来,合力对付敌人,不要相互攻击。”稍稍犹豫了一下,随后点头同意了。 喜羊羊负责引开野的注意力,而则悄悄试图找到他的弱点。喜羊羊跳上一块岩石,引得野追赶自己,而则从侧面潜入。在一个机智的瞬间,找到了野的弱点——他的脚腕。 决定利用这个机会,痛击野的弱点。他使出浑身解数,将野痛苦地制服在地。喜羊羊则迅速找到一根粗大的绳子,将野绑了起来。 当其他小动物们重新围聚在一起时,他们看到喜羊羊站在一起,团结一致。他们都意识到,只有通过合作才能战胜敌人,保护自己的家园和朋友们。 从那天起,喜羊羊之间的关系发生了巨大的变化。他们不再仅限于争斗与对抗,而是携手合作,为了共同的目标而努力。这个故事告诉我们,即使是原本对立的人或者动物,只要能够团结一致,便能够战胜困难,实现更大的目标。 ### 回答3: 一直以来都想要捉住喜羊羊和他的朋友们,然而,每次计划都以失败告终。但是,却坚持不懈地追逐着喜羊羊。一天,终于找到了喜羊羊的家,他偷偷潜入并绑架了喜羊羊。但是,看着绑着自己的绳子正在松动,喜羊羊突然意识到不是一切都像他想像中的那样。 喜羊羊故意装出害怕的样子,引诱沿着山上陡峭的路逃跑。在一阵惊险的逃亡之后,喜羊羊摔倒了,紧紧地拉住了他,阻止了他坠落到悬崖下。看到这一幕,喜羊羊也萌发了改变的念头。 他对说:“我们一直为了争斗而浪费了多的时间和精力。为什么我们不能成为朋友呢?” 犹豫了一下,但最终还是同意了喜羊羊的提议。从那之后,喜羊羊开始一起工作,他们发现彼此在一起时更加强大。他们一起解决了许多难题,并帮助其他的动物朋友们。这个新团队的出现改变了整个草原的动物们之间的关系。 虽然有些动物一开始并不相信喜羊羊的改变,但他们的行动逐渐让大家看到了一个不同的他们。喜羊羊变得更加勇敢和善良,他们的事迹渐渐流传开来。 这个故事告诉我们,人们不该只根据外表判断一个人,而要看他们内心的真实面貌。有时候,一个小小的改变就能引发巨大的影响,喜羊羊的改变就是最好的例子。他们的友谊不仅改变了他们自己,也让整个动物世界更加美好。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 36
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值