委托与事件
来源:互联网 发布:vmware for mac破解版 编辑:程序博客网 时间:2024/06/05 07:34
面向对象编程:生活怎样,编程就怎样。现实世界是个什么样子,编程就是个什么样子。
用Visual Studio开发过Windows程序或是Web应用程序的人都该知道事件这一概念,比如最简单的就是单击一个按钮引发按钮的Click事件,而这个事件的添加往往是通过IDE来自动生成,比如对这样一个方法大家应该并不陌生:privatevoidbutton1_Click(object sender,EventArgs e),当我们单击一个按钮的时候,程序会自动执行这个方法中的代码,而且我们可以通过其中的参数获得事件源的一些信息,这样一个效果是怎样做到的呢,下面的内容会帮你解开这些疑问。
我们通过两个场景的模拟来讲解委托与事件。场景如下:
羊历3513年,青青草原上,羊羊族群已经十分兴旺发达。在羊羊一族里面已经有小镇,有学校,有超市,有美容院,所有羊羊族群的羊都幸福快乐地生活。
可是,在对岸的森林里,灰太狼带着他的妻子红太狼却对着一群群的肥羊咽着口水。
下面有两个需求场景需要我们来完成。
场景一:这天,喜羊羊,沸羊羊和懒羊羊在草原上吃草。
场景二:灰太狼只要叫一声“哈,我是灰太狼”,喜羊羊,懒羊羊和沸羊羊就说“不好,(灰太)狼来了,快跑!”。
委托(delegate)
委托声明定义一种类型,它用一组特定的参数以及返回类型来封装方法,一旦为委托分配了方法,委托将与该方法具有完全相同的行为。对于静态方法,委托对象封装要调用的方法。对于实例方法,委托对象同时封装一个实例和该实例上的一个方法。
注:委托的本质就是一个类,任何可以声明类的地方都可以声明委托。
我们通过场景一的模拟来讲解什么是委托:
1 未使用委托的实现方式
using System;
using System.Text;
namespace 场景一的模拟一
{
publicdelegate voidEatHandler(string arg);
classProgram
{
staticvoid HappyEat(string food)
{
Console.WriteLine("喜羊羊吃{0}",food);
}
staticvoid FattyEat(string food)
{
Console.WriteLine("懒羊羊吃{0}", food);
}
staticvoid ForceEat(string food)
{
Console.WriteLine("沸羊羊吃{0}", food);
}
staticvoid Main(string[] args)
{
stringfood ="grass";
EatHandler happyEat =newEatHandler(HappyEat);
EatHandler fattyEat =newEatHandler(FattyEat);
EatHandler forceEat =newEatHandler(ForceEat);
happyEat(food);
fattyEat(food);
forceEat(food);
Console.ReadLine();
}
}
}
2 使用委托的实现方式一
※对于静态方法,委托对象封装要调用的方法。
using System;
using System.Text;
namespace 场景一的模拟一
{
publicdelegate voidEatHandler(string arg);
classProgram
{
staticvoid HappyEat(string food)
{
Console.WriteLine("喜羊羊吃{0}",food);
}
staticvoid FattyEat(string food)
{
Console.WriteLine("懒羊羊吃{0}", food);
}
staticvoid ForceEat(string food)
{
Console.WriteLine("沸羊羊吃{0}", food);
}
staticvoid Main(string[] args)
{
stringfood ="grass";
//happyEat(food);
//fattyEat(food);
//forceEat(food);
EatHandler happyEat =newEatHandler(HappyEat);
EatHandler fattyEat =newEatHandler(FattyEat);
EatHandler forceEat =newEatHandler(ForceEat);
EatHandler eatHandlerChain = happyEat + fattyEat + forceEat;
//一旦为委托分配了方法,委托将与该方法具有完全相同的行为。
eatHandlerChain(food);
Console.ReadLine();
}
}
}
3 使用委托的实现方式二
※对于实例方法,委托对象同时封装一个实例和该实例上的一个方法。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 场景一的模拟二
{
classGoat
{
privatestring name;
publicGoat(string name)
{
this.name= name;
}
publicvoid Eat(string food)
{
Console.WriteLine("{0} eat {1}.",name,food);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 场景一的模拟二
{
publicdelegate voidEatHandler(string arg);
classProgram
{
staticvoid Main(string[] args)
{
Goat happyGoat =newGoat("Happy");
Goat fattyGoat =newGoat("Fatty");
Goat forceGoat =newGoat("Force");
EatHandler happyEat =newEatHandler(happyGoat.Eat);
EatHandler fattyEat =newEatHandler(fattyGoat.Eat);
EatHandler forceEat =newEatHandler(forceGoat.Eat);
EatHandler eatHandlerChain = happyEat + fattyEat + forceEat;
eatHandlerChain("grass");
Console.ReadLine();
}
}
}
事件(event)
事件是委托的一种特殊形式,在发生其他类或对象关注的事情时,类或对象可通过事件通知它们,事件对象处理通知过程。
我们通过场景二的模拟来讲解事件:
这就是我们的需求就是场景二,现在我们要求通过程序来演绎这个过程。
这里有两个问题需要解决:
问题一:程序需要几个类?
问题二:两个类之间有什么关系,或者说你如何来处理两个类之间的关系
我们先来看一下程序员小菜的的分析:
(一)小菜说,这个问题我们需要两个类:Wolf和Goat,当Wolf的Shout方法触发时,Goat就执行Run方法。
这里小菜说得很对,但是关键的问题在于,我们如何让Wolf的Shout方法触发时Goat就执行Run方法呢?写过程序的人都碰到过类似的问题,如当你单击一个按钮的时候,这时就自动执行一段代码,这两个问题是一样的。
(二)小菜说:这事简单,在主Main函数中先调用一下Wolf的Shout方法,然后再调用Goat的Run方法,这不就解决了。
这里小菜的思路演绎出来的故事是什么样的故事呢?故事应该是这样的:故事里一共有四个“人”物,灰太狼,喜羊羊,懒羊羊,还有一个就是你,当灰太狼来的时候,你在一边通知了喜羊羊和懒羊羊,然后懒羊羊才跑开。
我们要求的是当灰太狼的Shout方法执行时,自动执行Goat的Run方法,这样才合乎现实的逻辑。
(三)小菜又说:那我可以在Wolf类中关联Goat类啊,直接在Wolf的Shout方法中加入Goat的Run方法不也可以实现吗?
这里的问题是什么呢?这就相当于灰太狼跑两只羊面前去,说:嗨,哥们,我是灰太狼,你们快跑。如果真是这样的话,所有的狼就都饿死了,不出多久,狼将成国家一级保护动物被圈养在动物园里了。
那我们究竟该如何来演绎这个故事呢?最好的方法就是用委托事件。
(一) 我们先来看两行代码:
public delegate voidWolfShoutEventHandler();
这里声明了一个委托,名称是WolfShoutEventHandler,我们说过,委托是对函数的一种封装,它实现了类似C++中函数指针的功能,这个委托所能代表的方法是无参数,无返回值的方法。
public event WolfShoutEventHandlerWolfShout();
这里声明了一个对外公开的public事件WolfShout,它的事件类型是委托WolfShoutEventHandler(委托是一种数据类型),表明事件发生时,执行被委托的方法。
(二) 我们来看类Wolf和Goat的设计
class Wolf
{
private string name;
public Wolf(stringname)
{
this.name= name;
}
public delegate void WolfShoutEventHandler();
public event WolfShoutEventHandler WolfShout;
public voidShout()
{
Console.WriteLine("哈,我是{0}.",name);
if(WolfShout != null)
{
WolfShout();
}
}
}
class Goat
{
private stringname;
public Goat(stringname)
{
this.name= name;
}
publicvoid Run()
{
Console.WriteLine("灰太狼来了,{0}快跑",name);
}
}
class Program
{
static void Main(string[]args)
{
Wolf GreyWolf = new Wolf("Wolfy");
Goat FattyGoat = new Goat("Fatty");
Goat HappyGoat = new Goat("Happy");
GreyWolf.WolfShout += newWolf.WolfShoutEventHandler(FattyGoat.Run);
GreyWolf.WolfShout += newWolf.WolfShoutEventHandler(HappyGoat.Run);
GreyWolf.Shout();
Console.Read();
}
}
(三) 通过上面的内容,我们已经可以理解单击一个按钮自动执行一个代码的原理了,下面的例子可以让你知道sender和e有什么用?
我们对上面的例子稍做改动,首先增加一个WolfShoutEventArgs,让它继承EventArgs,EventArgs是包含事件数据的类的基类,也就是说,这个类是用来在事件触发时传递数据用的。WolfShoutEventArgs类实际代码如下:
class WolfShoutEventArgs:EventArgs
{
private string name;
public string Name
{
get{ return name; }
set{ name = value; }
}
}
class Wolf
{
private string name;
public Wolf(stringname)
{
this.name= name;
}
public delegate void WolfShoutEventHandler(object sender,WolfShoutEventArgsargs);
public event WolfShoutEventHandler WolfShout;
public voidShout()
{
Console.WriteLine("哈,我是{0}.", name);
if(WolfShout != null)
{
WolfShoutEventArgse =newWolfShoutEventArgs();
e.Name = name;
WolfShout(this, e);
}
}
}
class Goat
{
private string name;
public Goat(stringname)
{
this.name= name;
}
public void Run(object sender,WolfShoutEventArgsargs)
{
//object sender 就是传送发送通知的对象
Console.WriteLine("{0}来了,{1}快跑",args.Name,name);
}
}
class Program
{
static void Main(string[]args)
{
WolfGreyWolf = new Wolf("Wolfy");
GoatFattyGoat = new Goat("Fatty");
GoatHappyGoat = new Goat("Happy");
GreyWolf.WolfShout += newWolf.WolfShoutEventHandler(FattyGoat.Run);
GreyWolf.WolfShout += newWolf.WolfShoutEventHandler(HappyGoat.Run);
GreyWolf.Shout();
Console.Read();
}
}
上课时用的讲述委托与事件例子,望对大家有用,针对初学者,高手请略过。ppt与代码下载地址:http://download.csdn.net/detail/liusheng010/5854453
- 委托入门-事件与委托
- 委托与事件
- 委托与事件
- c# 委托与事件
- 委托与事件
- 事件与委托详解
- 委托与事件详解
- 委托与事件详解
- 委托与事件
- C#委托与事件
- 委托与事件
- 委托与事件
- 事件与委托趣谈
- 事件与委托
- 事件与委托趣谈
- 事件与委托
- 事件与委托趣谈
- 事件与委托趣谈
- C文件操作
- jdk7下httpclient请求https问题
- C# 枚举类使用
- 内存溢出报错解决
- 开发板,主机,Linux虚拟机互ping
- 委托与事件
- WCF小实例以及三种宿主
- TCP/Socket学习---以太网(RFC 894)帧格式
- java模板模式
- 鲁迅说中国人有毛病,而且说的很绝,有劣根性,以点盖面了。哪国人没有呢,确切地说哪国没几个呢,他们比我们多多了,怎么我遇到的人都很好呢,素质大大的,没得说,就是有一点小毛病,弱智
- UVA537- Artificial Intelligence?
- 2013腾讯编程马拉松初赛第一场(3月21日) 湫湫系列故事——减肥记I hdu 4508--- 完全背包
- Ural 1003. Parity
- TCP/IP学习----IP数据报格式