谈谈委托(delegate)

委托(delegate):
      在面向对象编程中,使用的都是对象,作为对象,它们都有很多共性,比如说,可以作为参数使用。
        
///
///方法PayFee接收字符串作为参数
///

private void PayFee(string message)
{
   MessageBox.Show(message);
}
方法PayFee(),接收的参数是字符串,我们也可以重载PayFee(),让它接收的参数为int,enum,class,struct或者其他类型,如果想接收的参数类型是个方法,是否可以呢?

 可以的,既然是面向对象编程,方法也是可以作为参数使用的。只是,方法比较特殊,它自己可以接收其他参数,也可以返回值。

 在一个可以接收参数、返回值的方法中,接收另一个同样可以有参数、返回值的方法作为参数,可以很容易的理解,但是执行起来,容易产生混淆。

为了避免可能会有的问题,引入的概念委托(delegate)。我们常用委托,比如请人代缴手机费,好像很简单啊,说一声,帮我代缴,回来给你钱。这样做,一般情况下,都会正常实现,或许因为你委托的人同你比较熟悉,可以信赖。但让我们分析一下,这其中可能遇到的问题:

1.委托人同意替你缴费,但是由于种种原因,忘记了替你缴费,或者忘记了当月缴费,导致了手机停机;
2.委托人不但没有替你缴费,还对你说已经缴费,并收了你的钱。

以上情况都可能会发生,也许概率很低,只有0.1%。然而在程序设计中,如果使用的委托也存在这样的概率,那么我们会发现陷入了灾难当中。所以,必须要求委托是安全的,可靠的。
委托的语法要求严格,需要指明作用域,接收参数的类型及数量和返回类型。
public delegate void DoPayFee(string message);

以上声名的委托,作用域是Public的,定义接收的参数(一个方法),这个方法接收的参数是字符串string,没有返回值。
这样就可以接收上面的PayFee()作为参数使用了。
//委托实例,即要帮你缴费的中间人,他接收PayFee()这个方法,即你要缴费
DoPayFee dopayfee=new DoPayFee(PayFee)
//执行代缴费 
dopayfee("帮我代缴电话费");

这样,你的要求肯定会被执行。

多点委托:(MultiCasting)
        现实当中,经常出现一个人接收多个人的委托作相似的事情。比如帮多个人代缴电话费,这件事的共同点是到相同的地方,见相同的人,作相同的事情,唯一的不同是,缴费金额不同。
        在程序设计中,我们称之为多点委托。
       

//3个委托实例,接收相同的方法作参数,也可以是不同的
//方法,但是返回类型和参数必须相同
DoPayFee payuser1=new DoPayFee(PayFee);
DoPayFee payuser2
=new DoPayFee(PayFee);
DoPayFee payuser3
=new DoPayFee(PayFee);
//实现多点委托
DoPayFee paytotal=payuser1+payuser2+payuser3;
//执行
paytotal("给我们缴费");

因为最后的参数是由多点委托统一接收的,即每个单独的委托都接收相同的参数,所以我们只能给它口信,让它帮我们代缴费,至于金额,需要定义不同的PayFee方法,PayFee1(),PayFee2(),PayFee3()来完成。

在很多的书籍中提到,使用多点委托,其调用的方法必须返回void,即不能够返回值,如上面的例子。但是并不是不可以在多点委托中使用带有返回值的方法,我们可以定义:

//3个返回值得方法,假设返回值代表缴费金额
private int PayFee1(string message)
{
}

private int PayFee2(string message)
{
}

private int PayFee3(string message)
{
}
定义了上面的3个方法,让缴完费后,告诉我们费用是多少。
然后是用多点委托进行缴费:
//委托实例
DoPayFee payuser1=new DoPayFee(PayFee1);
DoPayFee payuser2
=new DoPayFee(PayFee2);
DoPayFee payuser3
=new DoPayFee(PayFee3);
//多点委托
DoPayFee paytotal=payuser1+payuser2+payuser3;
//执行,count代表缴费金额
int count=paytotal("给我们缴费");

 

执行完paytotal,只得到了一个结果,它覆盖了前面委托执行后的结果,即最后执行的委托调用的方法的结果,这同我们的初衷,得到每个缴费金额不同,有什么方法解决呢?

//循环执行每个委托,获取结果
foreach(DoPayFee payfee in paytotal.GetInvocationList)
{
   
int count=payfee("缴费");
}

posted on 2006-01-04 11:51  Pierce  阅读(435)  评论(0编辑  收藏  举报

导航