第11章 委托与事件教材_第1页
第11章 委托与事件教材_第2页
第11章 委托与事件教材_第3页
第11章 委托与事件教材_第4页
第11章 委托与事件教材_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第11章

委托(代表)与事件11.1委托(代表)11.2事件11.3事件访问器总结11.1委托

11.1.1前言

11.1.2定义

11.1.3定义委托对象及实例化

11.1.4用例

11.1.5进一步理解委托

11.1.6

组播(多重)委托返回首页11.1.1前言什么是委托?

函数是一个程序运行的代码段,调用该函数,相当于执行了这段代码段.

有时,我们需要实现这样一个功能:

定义一个特殊”变量”,此变量的内容为地址,----指向某个函数的代码段(首地址);

这样,当我们”调用”该”变量”时,程序就跳转到代码段去执行了.

这个特殊”变量”就是C,C++中的函数的指针

因为一个函数有签名有返回值,所以在C#中,我们将此”变量”看成是某个”类”生成的对象,这样我们把定义的这个”类”称为:委托(代表,代理,委派)

委托的实质委托实质上一种类型,即它的地位处于与类(class),结构(struct),枚举(enum)一样委托在定义好之后,必須”实例化””对象”才成使用.委托的”对象”可以用作类,结构的数据成员看待(“引用类型”)委托的”对象”当然也可以用作方法成员的参数看待11.1.2定义

delegate

返回类型委托名(形参1,…);例1:delegatevoidRun();//定义了一个叫Run的委托

//Get实例化后的可以代表所有无参数,无返回值那一类的函数

//如voidMain()voidFun()….

例2:delegateint

Handle(string

str);//定义了一个叫Handle的委托

//它可以指向int

Fun(string

str);//intFun1(stringstr);//…11.1.3

定义委托对象及实例化委托名对象名;对象名=全名.方法名;委托名对象名=new委托名(初始化参数);

例1:publicstaticvoidMain(){Runmain;//定义一个Get类型的变量mainmain=Main;//

main将voidMain()的代码段指向

//Runmain=newRun(Main);//实例化mainmain();//执行Main代码段,此例将形成死循环}

注意:1.委托仅仅是一个类型,故一定要定义一个变量才能使用

2.变量在初始时,只需将”方法名”赋给它

3.变量的使用,要把它看成方法的调用来理解

11.1.4

用例例1:委托对象当成局部变量例用classAPP{

publicstaticvoidMain(){//Runr1;//定义一个Run类型的变量r1

Runr1=newRun(Run1);//实例化r1,并初始r1();//执行Run1代码段

Aa=newA();

r1=a.Fun1;r1();//执行了a.Fun1();}publicstaticvoidRun1(){

Console.WriteLine(“inRun1”); }}

classA{

publicvoidFun1(){Console.WriteLine(“inFun1”);}}11.1.4用例例2:委托对象当成类(结构)的数据成员使用classAPP{

publicstaticvoidMain(){Bb1=newB();b1.r=newRun(b1.Fun1);b1.r();//执行了b1.Fun1()b1.r=Run1;b1.r();//相当于执行了APP.Run1();}publicstaticvoidRun1(){

Console.WriteLine(“inRun1”); }}

classB{

publicRunr;publicvoidFun1(){Console.WriteLine(“inFun1”);}}11.1.4

用例例3:委托对象有参数和返回值时的使用classAPP{

publicstaticvoidMain(){Cc1=newC();=“张飞”;c1.Active=hack;

intresult=c1.Active();//执行

Console.WriteLine(result);//了解完成情况}publicstaticint

hack(string

str){

Console.WriteLine(“我是:{0}”,str);//完成砍的动作

Console.WriteLine(“我在砍柴”);

int

结果=0;

return结果; }}

classC{publicstringname;

publicHandleActive;}11.1.5

进一步理解委托1.委托使动作名词化,是函数的进一步抽象

2.委托的出现,使程序能完成一些特殊的功能如:delegate菜加工方法(params

原料[]f);class厨师{public加工方法加工;}class菜{…}class原料{publicstring名称;..}classXX烹调大全{staticpublic菜煮(params

原料[]f){...}staticpublic菜炒(params

原料[]f){…}staticpublic菜蒸(params

原料[]f){…}}

11.1.5

进一步理解委托

1.委托使动作名词化,是函数的进一步抽象

2.委托的出现,使程序能完成一些特殊的功能如:classXX饭店{publicstaticvoidMain(){

厨师张三=new厨师();原料鱼=new原料();

张三.加工=XX烹调大全.煮;

菜菜1=张三.加工(鱼);//得到了煮鱼

张三.加工=XX烹调大全.炒;

菜菜2=张三.加工(鱼);//得到了炸鱼//……}}

将加工方法定义成委托的好处:使张三通过”不断地学习”可以”学会”不同的烹调方法11.1.5

进一步理解委托3.作为回调处理方法的一种机制如系统用此方法来接收消息,和处理事件例:delegatevoidHandl(string

发送人,string消息);

class消息{publicstring消息名;publicHandl

处理;}

class系统{

publicstatic消息[]消息箱=new消息[5];publicstaticvoid加入消息队列(stirng

消息名,Handl

处理方法){//加入消息…}staticvoid处理消息(){//定期检查消息队列,有信就调用相应的处理方法….

执行消息箱[i].处理(发送人1,消息1)}}

class本程序{publicstaticvoidMain(){

系统.加入消息队列(“有我的信”,通知我);}publicstaticvoid通知我(string消息){

console.writeLine(“事情为:”+消息);}注意:本例仅为模拟系统信息处理,,与实际情况差异较大!!!(见P311,E12-6)11.1.6

组播委托(广播,多播)

多个委托代码可以联合起来,实现执行一个委托变量而顺序调用多个代码段的能力添加委托委托变量=待加入委托变量1+待加入委托变量2+…;委托变量+=待加入委托变量;委托变量+=new委托(方法名);

移除委托变量-=待加入委托变量;委托变量-=new委托(方法名);

例:p311E12-6重要!!!,理解此知识点会更容易理解事件

11.2

事件

11.2.1前言

11.2.2定义和简单示例11.2.3使用系统定义的类型11.2.1前言

想象一下:生活中的事件历史

赤壁之战9.18事变新中国成立我的人生当我XX岁生日,当我大学毕业,我的第一份薪水门被打开,被关闭按钮被按下,被放开,正被按下,正被放开在软件中,为了让类和类的实例之间更好的通信,C#为我们定义了事件(event)事件是一种对象间传递消息的一种方式.通过事件,可以将事件名与具件事件联系起来.

如:

每个人都有XX岁生日事件,但是每个人的XX岁生日所发生的都不相同.每个按钮都有按下,放开事件,都每个按钮按下,放开的处理和结果都不相同.11.2.2定义和简单示例

事件是类的成员,定义:…修饰符

event

委托类型事件名;….例1:classDoor{publicevent

EventHandlerOpening;//正在开门

public

event

EventHandlerOpened;//已开门publicevent

EventHandlerClosing;//正在关门publicevent

EventHandlerClosed;//已关门}例2:classButton{

event

EventHandler

Cliek;//单击

event

EventHandler

DubClick;//双击}

假设:EventHandler

委托原型为

delegatevoidEventHandler();

11.2.2定义和简单示例进一点完善门类,加入两个动作:开门关门例1:class门{publicevent

Event_HandlerOpening;//正在开门

public

event

Event_HandlerOpened;//已开门publicevent

Event_HandlerClosing;//正在关门publicevent

Event_HandlerClosed;//已关门

publicvoidOpen(){

if(Opening!=null)Opening();//发送正在开门消息

//做开门的动作

//…

if(Opened!=null)Opened();//发送门已被打开的消息 }

publicvoidClose(){

if(Closing!=null)Closing();//发送正在关门消息

//做关门的动作

//…

if(Closed!=null)Closed();//发送门已被关闭的消息 }}11.2.2定义和简单示例如何使用门例1:class房子{publicstatic门前门=new门();;//定义,并实例化一扇门publicstaticvoidMain(){前门.Opening+=newEvent_Handler(OnOpening);//把处理方法挂到Opening方法上去前门.Opened+=newEvent_Handler(OnOpened);//把处理方法挂到Opened方法上去

while(true){

Console.WriteLine(“请输入动作:0-开门C-关门q-结束程序”);

switch(Console.ReadLine()){case“o”: 前门.Open();//开门;break;case“c”: 前门.Close();//关门;break;case“q”:return;}

} }

publicstaticvoidOnOpening(){

Console.WriteLine(“门正被我打开!”);}publicstaticvoidOnOpened(){

Console.WriteLine(“门已打开!!!”);}….}11.2.2定义和简单示例修饰符:

访问修饰符publicprotecedprivateinternal….

其它修饰符newstaticvirtualseadleoverrideabstract

意义:(见类的成员修饰符)事件类型:

事件的类型一定是委托类型;其:1.可以自行定义(见例1,例2);

2.也可以使用系统已定义好的类型;

例:delegatevoidEventHandler(objcet

send,XXXEventArgs

e)

参数:send通常是指引发事件的对象,

e是用来存放事件发生时传送来的数据

(注意:类型为XXXEventArgs,均派生于EventArgs,这个系统定义好的类)

返回值void3.也可以按系统的要求,派生参数e的类型,,以得到不同的委托

11.2.3使用系统定义的委托类型例:进一点改进例1//定义委托

delegatevoidEventHandler(object

send,DoorEventArgs

e);//处理”门”事件可能需要用到的数据对象

classDoorEventArgs:EventArgs{publicstringMessage;publicDoorEventArgs(stringm){Message=m;}}11.2.3使用系统定义的委托类型//门的定义

classDoor{publicstring名称;

publiceventEventHandlerOpening;//正在开门

publiceventEventHandlerOpened;//已开门

publiceventEventHandlerClosing;//正在关门

publiceventEventHandlerClosed;//已关门

publicDoor(){}publicDoor(string名){名称=名;}publicvoidOpen(objectsend){

if(Opnening!=null)

Opening(send,newDoorEventArgs(this.名称));//Dosomething

if(Opned!=null)

Opened(send,newDoorEventArgs(this.名称));}publicvoidClose(objectsend){

if(Closeing!=null)

Closing(send,newDoorEventArgs(this.名称));//Dosomething

if(Closed!=null)

Closed(send,newDoorEventArgs(this.名称));}}11.2.3使用系统定义的委托类型//事件驱动的”主程序”class房子

{publicstring名称;publicDoor大门;public房子(){}public房子(string名){

大门=newDoor("大门");//定义,并实例化一扇门名称=名;}publicvoidInit(){

大门.Opening+=newEventHandler(OnOpening);//把处理方法挂到Opening方法上去大门.Opened+=newEventHandler(OnOpened);//把处理方法挂到Opened方法上去大门.Closing+=newEventHandler(OnClosing);

大门.Closed+=newEventHandler(OnClosed);}publicvoidOnOpening(objectsend,DoorEventArgse){Console.WriteLine("{0}的{1}正在打开",((房子)send).名称,e.Message);}publicvoidOnOpened(objectsend,DoorEventArgse){Console.WriteLine("{0}的{1}已打开",((房子)send).名称,e.Message);}

…}11.2.3使用系统定义的委托类型//底层系统classApp{static房子h;

publicstaticvoidMain(){

Init();//系统初始化

do{Console.WriteLine("************************************************************");Console.WriteLine("请输入动作:o-开门c-关门e-清除屏幕q-结束程序");Console.WriteLine("************************************************************");switch(Console.ReadLine()){case"o":

h.大门.Open(h);break;case"c":

h.大门.Close(h);break;

case"e":Console.Clear();break;case"q":return;}}while(true);}publicstaticvoidInit(){

h=new房子("陈公馆");

h.Init();//初始化}}11.3事件访问器11.3.1前言11.3.2定义11.3.1前言为什么使用事件访问器?

事件可以理解为是委托的一种特例.

事件在使用上比委托受了一些限制(为了更有意义的使用事件)

1.事件的类的成员,用event定义委托是一种类型,委托的实例才是类的成员

delegatevoidHandle();//委托

classA{publiceventHandleclick;//事件成员

publicHandleFun;//委托成员

}

2.事件仅能用+=-=加挂或脱离方法委托的实例对象可以用=号与方法挂勾,也可以使用+=,也可以使用-=脱勾

click+=newHandle(B.fun);click-=newHandle(B.fun);

Fun=newHandle();Fun=B.fun;Fun=null;Fun+=newHandle(B.fun);Fun-=newHandle(B.fun);Fun+=B.fun;

11.3.1前言为什么使用事件访问器?3.系统在编译时会默认为事件添加上事件访问器而委托的成员却不会自动添加.

什么是事件访问器?

将委托实例成员封装成事件(加挂和移除方法)

//字段与属性

privateint_a;

publ

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论