C#委托与事件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Zhangyuanxuevaq/article/details/79979419

C#委托与事件

一、委托(C#中的委托就是C++中的回调函数)

记得在使用C语言的年代,整个项目中都充满着针指的身影,那时候流行使用函数指针来创建回调函数,使用回调可以把函数回调给程序中的另一个函数。但函数指针只是简单地把地址指向另一个函数,并不能传递其他额外信息。
.NET中,在大部分时间里都没有指针的身影,因为指针被封闭在内部函数当中。可是回调函数却依然存在,它是以委托的方式来完成的。委托可以被视为一个更高级的指针,它不仅仅能把地址指向另一个函数,而且还能传递参数,返回值等多个信息。系统还为委托对象自动生成了同步、异步的调用方式,开发人员使用 BeginInvokeEndInvoke 方法就可以抛开 Thread 而直接使用多线程调用 。

当要把方法作为实参传送给其他方法的形参时,形参需要使用委托委托是一个类型,是一个函数指针类型,这个类型将该委托的实例化对象所能指向的函数的细节封装起来了,即规定了所能指向的函数的签名,也就是限制了所能指向的函数的参数和返回值。当实例化委托的时候,委托对象会指向某一个匹配的函数,实质就是将函数的地址赋值给了该委托的对象,然后就可以通过该委托对象来调用所指向的函数了。

一般的调用函数,我们都不会去使用委托,因为如果只是单纯的调用函数,使用委托更麻烦一些;但是如果想将函数作为实参,传递给某个函数的形参,那么形参就一定要使用委托来接收实参,一般使用方法是:在函数外面定义委托对象,并指向某个函数,再将这个对象赋值给函数的形参,形参也是该委托类型的对象变量,函数里面再通过形参来调用所指向的函数(相关demoC#\DelegateDemo\DelegateDemo)。

委托使用方法

1、先声明。如:delegate void MyDelegate(string message);

2、定义委托对象并用合适(函数有一个string 类型形参的,且返回值类型为void型的)的函数初始化该委托对象,如: MyDelegate myDelegate = new MyDelegate(example.Method);

3、执行委托,如: myDelegate("Hello World");

二、事件

简介:事件(event)可被视作为一种特别的委托,它为委托对象隐式地建立起add_XXXremove_XXX 两个方法,用作注册与注销事件的处理方法。而且事件对应的变量成员将会被视为 private 变量,外界无法超越事件所在对象直接访问它们,这使事件具备良好的封装性,而且免除了add_XXXremove_XXX等繁琐的代码。

事件能通过+=-=两个方式注册或者注销对其处理的方法,使用+=-=操作符的时候,系统会自动调用对应的 add_XXXremove_XXX 进行处理。

使用方法:

1、声明一个委托:

Delegate result-type delegateName ([parameters]);

例如:  delegate void MyDelegate(string message);

这个委托可以在类A内定义也可以在类A外定义。

2、在类里面声明一个基于某个委托的事件

Event delegateName  eventName

eventName不是一个类型,而是一个具体的对象,这个具体的对象只能在类A内定义而不能在类A外定义。

3在类A中定义一个触发该事件的方法

ReturnType  FunctionName[parameters]

{

 ……

If(eventName != null)

{

eventName[parameters]);

或者eventName.Invoke[parameters]);

}

……

}

事件处理方法的绑定

A personManager = new A();

A.eventName += new MyDelegate(GetName);//GetName是一个函数。

触发事件之后,事件所指向的函数将会被执行。这种执行是通过事件名称来调用的,就像委托对象名一样的。

触发事件的方法只能在A类中定义,事件的实例化,以及实例化之后的实现体都只能在A类外定义。

事件使用方法实例

1、首先在类外声明委托,如: public delegate void RaiseEventHandler(string hand);

2、在类A内声明基于该委托的事件,如: public event RaiseEventHandler RaiseEvent;

3、在其他类B中就可以订阅该事件了,订阅时需给委托初始化合适的函数(函数有一个string 类型形参的,且返回值类型为void型的)

如: a.RaiseEvent += new RaiseEventHandler(ab_RaiseEvent); // 订阅举杯事件,注意这里的ab_RaiseEvent函数必须是一个string 类型形参的,且返回值类型为void型的

4、在类A中写调用事件的函数。如: public void Fall(){ FallEvent();}

5、main函数中调用类A的调用事件的函数,如

 A a = new A(); // 定义首领A 

 B b = new B(a); // 定义部下B

 a.Fall();//执行该步订阅者会自动执行//对于控件事件的这一步应该在底层,自己看不到

 

总结:

事件是针对某一个具体的对象的,一般在该对象的所属A中写好事件,并且写好触发事件的方法,那么这个类A就是事件的发布者,然后在别的类B里面定义A的对象,并去初始化该对象的事件,让事件指向B类中的某一个具体的方法B类就是A类事件的订阅者。当通过A类的对象来触发A类的事件的时候(只能A类的对象来触发A类的事件,别的类的对象不能触发A类的事件,只能订阅A类的事件,即实例化A类的事件),作为订阅者的B类会接收A类触发的事件,从而使得订阅函数被执行。一个发布者可以有多个订阅者,当发布者发送事件的时候,所有的订阅者都将接收到事件,从而执行订阅函数,但是即使是有多个订阅者也是单线程。

控件事件

简介:比如当用户用鼠标去点击一个windows应用程序的按钮的时候,windows操作系统就会捕获到这个点击按钮的动作,这个时候它会根据捕获到的动作发送一个与之对应的预定义的消息给windows应用程序的这个按钮,windows应用程序的按钮消息处理程序会处理接收到的消息,这个程序处理过程就是根据收到的消息去触发相应的事件,事件被按钮触发后,会通知所有的该事件的订阅者来接收这个事件,从而执行相应的的函数。

控件事件委托EventHandler:

在控件事件中,有很多的委托,在这里介绍一个最常用的委托EventHandler,.NET Framework中控件的事件很多都基于该委托,EventHandler委托已在.NET Framework中定义了。它位于System命名空间:

Public delegate void EventHandler(object sender,EventArgs e);

控件事件的MouseEventHandler委托使用实例:

Public delegate void MouseEventHandler(object sender,MouseEventArgs e);//定义委托

public event MouseEventHandler MouseDown;//定义事件

this.MouseDown+= new System.Windows.Forms.MouseEventHandler(this.Form1_MouseDown);

private void Form1_MouseDown(object sender, MouseEventArgs e){};//定义具体的方法

MouseDown事件使用MouseDownEventArgs,它包含鼠标的指针在窗体上的的X和Y坐标,以及与事件相关的其他信息。

注意:

1控件事件中,一般第一个参数都是object sender,第二个参数可以是任意类型,不同的委托可以有不同的参数,只要它派生于EventArgs即可。

2、其中.NET框架已有的代码,当在控件的属性栏为控件添加事件时,会在Form1.Desinger.cs文件中自动生成和在Form1.cs中自动生成的框架(无实现),功能代码部分需要自己写。从C#框架代码部分可以让我们自己学习到如何写此类功能。

3首先,事件处理程序(上面的④)总是返回void,事件处理程序不能有返回值。其次是参数,只要是基于EventHandler委托的事件,事件处理程序的参数就应是object和EventArgs类型:其中第一个参数接收引发事件的对象,比如当点击某个按钮的时候,这个按钮要触发单击事件最终执行这个函数,那么就会把当前按钮传给sender,当有多个按钮的单击事件都指向这个函数的时候,sender的值就取决于当前被单击的那个按钮,所以可以为几个按钮定义一个按钮单击处理程序,接着根据sender参数确定单击了哪个按钮:

if(((Button)sender).Name =="buttonOne")。第二个参数e是包含有关事件的其他有用信息的对象。

 

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页