这个指南叙述了一些C#语言中的主要特性,即委托和事件。

文章中源代码地址:

http://www.codeproject.com/useritems/Deligates/Deligates.zip

导言

什么是委托?

我们都熟悉函数。函数执行预先定义的一组操作并且根据传入的参数来返回结果。例如,函数AddOper(a,b)将两个数a和b相加然后返回这两个数的和。现在我们来考虑写一个通用的函数。这个函数可以执行许多任务。我们假设它能完成数字的加,减,乘的操作。

写这个函数的一种方式可以传递我们想要执行操作的类型和值来作为参数。例如:AddOper(a,b,"add")来实现a和b相加。在函数内部,我们使用Select Case或者if else语句来决定我们想要执行操作的类型。这种方法有明显的复杂度和局限性。

我们想要一种非常灵活而且普通的解决方法。我们想写一个被主应用程序(Main Application)调用的普通函数来代替调用特定的函数。这正是我们所希望的。

现在的问题是,是否有可能写出这样灵活的应用程序呢?

答案是肯定的,我们可以实现将一个方法传递给另一个方法。就像GenericFun(AddOper)这样。然而,出于类型安全的原因,C#不建议这样的实现方法。为达到同样的目的,C#提出了一种叫做DELEGATE(委托)的新对象。

与类(Class)类型相似,我们定义委托(Delegate)类型,然后创建一个委托的实例来控制函数的细节,请注意这个实例只包含函数名和返回类型的详细信息,并不包含函数体。

声明一个委托的语法如下:

Public delegate int GenericFun(int a, int b);

以上定义的这个委托接受返回类型为整型并且带有两个整型参数的函数。

我们想要对以下这个加法函数起作用:

Private int AddOper(int a,int b){}

现在我们创建这个委托的一个实例然后将我们的加法函数传入这个委托。

GenericFun gfAdd = new GenericFun(AddOper);

可以看到委托的构造函数接受函数名作参数。

现在,让我们来看一下我们如何将这个委托传递到一个普通的函数PrintResult中,这个函数可以操纵两个数字并且返回一个整数。它可以用来打印加,减乘或者任意过程的类型的结果,这些过程带有两个整型参数并且返回一个整数。现在,让我们看一看如何构造PrintResult来处理两个数相加。

//定义两个要相加的数字

int No1=40;

int No2=60;

//调用普通函数来将这些数相加

PrintResult(gfAdd,No1,No2)

你将在控制台看到100的结果。

现在我们将看到PrintResult方法是如何定义的。

Private int PrintResult(GenericFun action,int a,int b){

int result=action(a,b);

console.WriteLine(result);

}

你有没有注意到这样神奇的效果!只是创建了一个委托的实例,传入一个要协作的函数名然后调用普通函数,并将委托传入就可以得到你想要的结果。重复相同的过程,实现减法函数,操作如下:

GenericFun gfSub = new GenericFun(SubOper);

PrintResult(gfSub,No1,No2);

我们可以定义一个委托数组,然后定义每一个独立的委托。我们可以按如下操作:

GenericFun[] gf = {new GenericFun(AddOper),new GenericFun(SubOper)};

然后执行减法操作,使用如下的语法:

PrintResult(gf1,No1,No2);

让我们看一下如何将委托和事件一起使用。注意事件是代理的一种类型。

为了明白委托是什么以及如何使用委托,让我们从一个简单的例子开始。一个银行有一个呼叫中心,它接受ATM卡的信息。在接受到信息后,银行系统通过一下一种方式发送客户的信息:

Email,通过SendEmail按钮提供一个可用的email地址。

Fax,通过SendFax按钮提供一个可用的传真号码,或者当email地址或者传真号码都无效的情况下,可以通过信函,通过SendLetter按钮发送。

所以我们需要三个事件句柄来控制以下时间中的一个:

SendEmailEvent_handler

SendFax_handler

SendLetter_handler

我们需要一个被主应用程序调用的普通函数然后依次调用适当的时间句柄。

我们写三个类,这三个类分别叫做Email,Fax和Letters。每个类都有自己发送信息的方法。所以Email类有SendEmailMessage方法,Letter类有SendLetter方法,Fax类有SendFax方法来发送信息。

我们需要的另一个类叫做MessageWatcher,这个类根据用户的选择调用适当的发送方法。

我们还要设计一个带有三个按钮的Form,每一个按钮用来发送一种类型的消息。当点击SendEmailMessage按钮时,产生一个事件,MessageWatcher类截取这个事件然后调用适当的事件句柄。在这个例子中调用的是Email类的SendEmailMessage方法。让我们看一下是如何做到的。

MessageWatcher类和原始函数SendMessage如下。

//定义发送信息的MessageWatcher类

public class MessageWatcher {

//定义消息委托

public delegate void MessageHandler(object Sender, MessageInfo mi);

//定义一个事件

public event MessageHandler OnMessageSendRequest;

//这个函数响应发送的消息

public void SendMessage(MessageInfo mr) {

//判断是否被定义

if (OnMessageSendRequest !=null)

OnMessageSendRequest(this,mr);

}

注意OnMessageSendRequest(this,mr)函数带有两个参数并且不返回任何任何值。比较以下的SendEmailMessage函数。

public void SendEmailMessage(object Sender,MessageInfo ei){}

非常重要的是所有的函数形式和原始函数有相同的形式。所以SendEmailMessage和OnMessageSendRequest(this,mr)应该匹配参数和返回类型。

现在的问题是MessageWatcher类如何决定它必须嗲用SendEmailMessage句柄呢?首先,Email类需要通知Watcher类它将要处理SendEmail事件并且在它的构造函数中传入。语法如下:

public Email(MessageWatcher mw){

//存储watcher引用

watcher=mw;

//告诉MessageWatcher类它将要处理SendEmail事件

watcher.OnMessageSendRequest+=new

MessageWatcher.MessageHandler(SendEmailMessage);

}

当Email类被实例化后,它通知MessageWatcher类OnMessageSendRequest事件发生了,它将处理这个事件。

你注意了没有,MessageHandler是一个委托,我们很简单的传入了函数名SendEmailMessage。所以Email类通知MessageWatcher类他要处理SendEmailMessage事件。

最后,在主应用程序中我们写了三行代码。

//创建email类的实例

MessageWatcher mw=new MessageWatcher();

Email em=new Email(mw);mw.SendMessage(mi);

当点击SendEmailMessage按钮后,主应用程序创建一个MessageWatcher类和Email类的实例。Email类的构造函数传入一个观察者类的实例。当Email类被实例化后,它通知MessageWatcher实例它将要处理SendEmailMessage事件。最终,主应用程序调用MessageWatcher类的原始函数SendMessage,传入MessageInfo数据结构。

SendMessage函数MessageWatcher类产生OnMessageSendRequest(this,mr)事件,因为Email类已经通知MessageWatcher类他将处理SendEmailMessage事件因此SendEmail函数来处理这个事件。

Email类利用.Net的System.Web类来发送emails。

Letter类使用Microsoft Word库。因为这个库是一个COM组件因此我使用System.Runtime.InteropServices。这个类使用模板文字来插入客户文本。

有关作者lakshmi patil
三年软件工程师工作经验,工作领域asp.net,C#,xml,xslt,sqlserver,JavaScript和infragistics web控件。

解C#中的委托(Deligate)相关推荐

  1. 理解C#中的委托(Deligate)

    理解C#中的委托(Deligate)   原作者:lakshimi patil    翻译:tongzhiyong 这个指南叙述了一些C#语言中的主要特性,即委托和事件. 导言 什么是委托? 我们都熟 ...

  2. C# 中的委托和事件(详解) ....

    C# 中的委托和事件 委托和事件在 .NET Framework 中的应用非常广泛,然而,较好地理解委托和事件对很多接触 C# 时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太 ...

  3. C# 中的委托和事件(深入浅出的详解)

    C# 中的委托和事件 引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真 ...

  4. C# 中的委托和事件--详解(续)

    引言 如果你看过了 C#中的委托和事件 一文,我想你对委托和事件已经有了一个基本的认识.但那些远不是委托和事件的全部内容,还有很多的地方没有涉及.本文将讨论委托和事件一些更为细节的问题,包括一些大家常 ...

  5. C# 中的委托和事件--详解

    文中代码在VS2005下通过,由于VS2003(.Net Framework 1.1)不支持隐式的委托变量,所以如果在一个接受委托类型的位置直接赋予方法名,在VS2003下会报错,解决办法是显式的创建 ...

  6. 详解Objective-C中委托和协议

    Objective-C委托和协议本没有任何关系,协议如前所述,就是起到C++中纯虚类的作用,对于"委托"则和协议没有关系,只是我们经常利用协议还实现委托的机制,其实不用协议也完全可 ...

  7. 详解OpenCV中的Lucas Kanade稀疏光流单应追踪器

    详解OpenCV中的Lucas Kanade稀疏光流单应追踪器 1. 效果图 2. 源码 参考 这篇博客将详细介绍OpenCV中的Lucas Kanade稀疏光流单应追踪器. 光流是由物体或相机的运动 ...

  8. C#中的委托和事件(续)

    引言 如果你看过了 C#中的委托和事件 一文,我想你对委托和事件已经有了一个基本的认识.但那些远不是委托和事件的全部内容,还有很多的地方没有涉及.本文将讨论委托和事件一些更为细节的问题,包括一些大家常 ...

  9. C# 中的委托和事件

    引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去 ...

最新文章

  1. 【C语言】libiniparser库使用例子,
  2. linux挂载移动硬盘 格式化_linux系统下如何挂载NTFS移动硬盘
  3. 理解Hinted Handoff
  4. 汤家凤高等数学基础手写笔记-曲线与曲面积分
  5. php登陆框_PHP 登录完成跳转上一访问页面
  6. 【软件工程】用户在软件项目中承担的工作
  7. Css 基本的规则写法
  8. python参数解析模块sys、getopt、argparse学习使用与对比分析
  9. android 定时重启手机,有必要定时重启手机吗? 重启后手机会更流畅吗?
  10. 计算机1级b知识点,初中信息技术等级考试知识点
  11. android表情转码,UCS-4 android/ios微信emoji表情转码
  12. swf播放器air android 版,网极SWF播放器(com.webgenie.swf.play) - 1.6.3 - 应用 - 酷安
  13. 伽罗华有限域_伽罗华域(Galois Field,GF,有限域)乘法运算 | 学步园
  14. for while循环练习
  15. 百度bae部署html,百度BAE使用:应用配置文件 app.conf
  16. Weakly-Supervised Salient Object Detection via Scribble Annotations
  17. 阿里云5天学习感悟与案例分享
  18. go学习笔记接口部分
  19. 2013年07月15日
  20. 论文 文献引用字体颜色更改为蓝色

热门文章

  1. 宠物消费升级 “黑科技”带来了哪些改变?
  2. 机器学习:矩阵、向量求导理解
  3. 2019年山东省深思杯网络安全大赛
  4. mysql删除表中的一列数据_在数据表中添加或删除一列
  5. 在鸿蒙开发板上使用MQTT协议、OneNET实现第一个物联网项目
  6. Openwrt系统编译
  7. python交通标志识别_DataFountain-基于虚拟仿真环境下的自动驾驶交通标志识别 4th...
  8. 数据挖掘Java——DBSCAN算法的实现
  9. vue基于腾讯云cos部署
  10. IT职场人生系列之六:员工的公司观