解C#中的委托(Deligate)

这个指南叙述了一些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控件。

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值