论C#中的委托与事件

合集下载
相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

论C#中的委托与事件

在C#里,委托与事件类是两个不易理解的概念。主要阐述对委托与事件的理解,同时结合Observer设计模式与.NET Framework规范,针对生活中的案例来辨析委托与事件的应用。

标签:委托;事件Observer设计模式;.NET Framework

C#中的委托类似于C++中的函数指针,功能却更多。事件是在委托的基础上的一种结构,类似于委托的变量,在界面的控件中处处都有应用。

1 什么是委托

委托的申明格式:修饰符delegate 返回值数据类型委托名(形参列表)。

例如:Delegate int AbcDel(string s, bool b);是一个委托申明,每一个委托都有自己的签名,就是说AbcDel这个委托有string 和bool类型的形参,返回一个int类型数据,即具有这样的函数签名。委托类似于函数指针,它能够引用函数,通过传递地址的机制完成。委托是一个类,当对它实例化时,要提供一个引用函数,将其作为它构造函数的参数。例如:private int AbcFun (string str, bool bln){},则可以把这个函数传给AbcDel的构造函数,因为它们签名一致。AbcDel sd = new SomeDelegate(AbcFun),sd 引用了AbcFun,也就是说,AbcFun已被sd所登记注册,如果你调用sd,AbcFun这个函数即会被调用。

2 事件的理解

事件的申明格式:修饰符event 委托名事件名;

例如:public event AbcDel Boil;//AbcDel为委托名

Boil事件的声明与之前委托变量sd的声明唯一的区别是多了event关键字。声明事件类似于声明一个委托类型的变量。

3 Observer设计模式

假设热水器系统由两部分组成:热水器、警报器,由不同厂商进行了组装。热水器仅负责烧水;警报器在水烧开时发出警报,当水温超过95度,就发出警报。我们需要应用委托与事件来模拟此过程。

Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新。Observer模式是一种松耦合的设计模式。它包括两类对象:

Subject:监视对象,它包含其他对象感兴趣的内容。热水器是一个监视对象,它包含temprature字段,当它>95时,会不断把数据发给监视它的对象。

Observer:监视者,它监视Subject,当Subject中的某件事发生时,会告知Observer,Observer即采取相应行动。Observer就是警报器。

在本例中,事情发生的顺序如下:

警报器告诉热水器,它对它的温度感兴趣(注册)。

热水器知道后保留对警报器的引用。

热水器进行烧水这一动作,当水温超过95度时,通过对警报器的引用,自动调用警报器的MakeAlert()方法。代码如下:

Heater类:

private int temperature;

public delegate void BoilHandler(int param);//声明委托

public event BoilHandler BoilEvent; //声明事件

public void BoilWater() { for (int i = 0; i 95) {if (BoilEvent != null) {//如果有对象注册

BoilEvent(temperature) ;} } }//调用所有注册对象的方法

Alarm类:public void MakeA lert(int param) {//…输出水温}

主函数主要代码如下:

heater.BoilEvent += alarm.MakeAlert;//注册方法

heater.BoilWater();//烧水,会自动调用注册过的方法

输出:Alarm:嘀嘀嘀,水已经96度了:

Alarm:嘀嘀嘀,水已经97度了:// ...

4 Net Framework中的委托与事件

上面的代码很好地完成了工作,但.Net Framework中事件模型有所不同,.Net Framework的编码规范如下:

(1)委托类型名称都以EventHandler结束;

(2)委托的原型定义:返回值void,接受两个输入参数:一个Object 类型,一个EventArgs类型(或继承自EventArgs,但类型名要以EventArgs结尾);

(3)事件的命名:委托去掉EventHandler之后剩余的部分。

委托声明原型中的Object类型的参数代表了Subject,即监视对象,在本例中是Heater。回调函数(Alarm的MakeAlert)可以通过它访问触发事件的对象(Heater)。EventArgs对象包含了Observer感兴趣的数据,即temperature。

上面这些不仅是为了编码规范,也使程序更灵活。将热水器的引用传给警报器的方法,就可以直接访问热水器的温度、型号等。按.Net Framework改写此例:

Heater类代码如下:

public string type = “RealFire 001”;//型号

public delegate void BoiledEventHandler(Object sender, BoliedEventArgs e);

public event BoiledEventHandler Boiled;

public class BoliedEventArgs : EventArgs { //定义BoliedEventArgs类,

public readonly int temperature;//传递给observer所感兴趣的信息

public BoliedEventArgs(int temperature) {this.temperature = temperature; }}

protected virtual void OnBolied(BoliedEventArgs e) {

if (Boiled != null) { Boiled(this, e); // 调用所有注册对象的方法} }

public void BoilWater() {

for (int i = 0; i 95) {

BoliedEventArgs e = newBoliedEventArgs(temperature);OnBolied(e); }}}

Alarm类代码如下:

public void MakeAlert(Object sender, Heater.BoliedEventArgs e) {

Heater ht = (Heater)sender;Console.WriteLine(“Alarm:{0},嘀嘀嘀,水已经{1}度

相关文档
最新文档