6 委托与事件
总的说来在.NET 平台上委托有三大作用:实现委托功能,实现回调函数功能,实现事件功能。
1 委托
当需要把方法传递给其它方法时,就需要使用委托。
1.1 声明委托
委托需要承载哪些信息呢?首先,它存储了方法名,还有参数列表(方法签名),以及返回的类型。比如:
delegate string/*返回类 型*/ ProcessDelegate(int i);
这就是一个委托的定义。蓝色部分是声明委托的关键字,红色部分是返回的类型,而黑色部分是委托的类型名,和一个类名差不多,而()里的就是参数部分。它的 意思是,你要使用这个委托来做事情的话,那么,做事情的方法必须满足以下条件:
1、返回类型和委托的返回类型一致,这里是string类型;
2、能且只能有一个参数,并且是int类型。
OK,满足以上两个条件,一切就可以工作了:)
例如:
2 using System.Collections.Generic;
3 using System.Text;
4
5 namespace TestApp
6 {
7 /// <summary>
8 /// 委托
9 /// </summary>
10 /// <param name="s1"></param>
11 /// <param name="s2"></param>
12 /// <returns></returns>
13 public delegate string ProcessDelegate(string s1, string s2);
14
15 class Program
16 {
17 static void Main(string[] args)
18 {
19 /* 调用方法 */
20 ProcessDelegate pd = new ProcessDelegate(new Test().Process);
21 Console.WriteLine(pd("Text1", "Text2"));
22 }
23 }
24
25 public class Test
26 {
27 /// <summary>
28 /// 方法
29 /// </summary>
30 /// <param name="s1"></param>
31 /// <param name="s2"></param>
32 /// <returns></returns>
33 public string Process(string s1,string s2)
34 {
35 return s1 + s2;
36 }
37 }
38 }
输出的结果是:
Text1Tex2
定义一个委托就是告诉编译器这种类型的委托代表了那种类型的方法,然后创建该委托的一个或多个实例,编译器在后台创建表示该委托的一个类。
在c#中,委托在语法上总是带有一个参数的的构造函数,这个参数就是委托引用的方法。这个方法必须匹配最初定义委托时的签名 。
c#2.0使用委托推断扩展了委托的语法,为了减少输入量,只需要委托实例,就可以只传送方法的名称。
例如 MyDelete MyDeleteDemo=new MyDelete(x.ToString) 可以写成MyDelete MyDeleteDemo=x.ToString; //只要把变量的方法名传递给委托实例就可以了
2 多播委托
委托可以包含多个方法,这种包含多个方法的委托称为多播委托。如果调用多播委托,就可以连续调用多个方法。为此,委托的签名就必须返回void类型,否则就只能得到委托调用的最后一个方法返回的结果。
通过一个委托调用多个方法存在一个问题。多播委托包含一个逐个调用的委托集合,如果通过委托调用 的一个方法抛出了异常,整个迭代就会停止。
3 匿名方法
使用委托还有另外一种方式,即通过匿名方法。匿名方法是用作 委托参数 的一个 代码块。
用匿名方法定义委托与前面的方法并没有区别。 但在实例化委托时就有区别 了。下面的例子说明如何使用匿名委托
namespace Demo.Delete
{
class DeleteDemo
{
deletegate string DeletegateTest(string val);
static void Main()
{
string strval="just a ";
DeletegateTest AnotherDel=new DeletegateTest(string param)
{
parm+=strval;
parm+="joke";
return parm;
};
Console.WriteLine(AnotherDel("my life is"));
}
}
}
匿名方法的好处是减少了要编写的代码,不必定义由委托使用的方法。如果需要使用匿名方法多次编写同一个方法,就不要使用匿名方法。而应该编写一个指定的方法比较好,这样只编写一次,以后就可以通过名称来引用它了。