知道C#的“委托”名词很久了,一直都没有需求去了解它,最近因为要写的系统以及nbpm萌生了了解它的想法。
初步看了一下委托,第一感觉委托本质上就是C/C++中的函数指针。不同的是委托是面向对象,其构造更复杂和灵活,但掌握了之后使用更方便。同时函数指针只能是静态方法,而委托可以是静态方法,也可以是实例方法。
委托使用分三步:1、委托声明。2、委托实例化。3、委托调用。
一、基本用法:
委托最基本的概念和方法使用下面的例子应该很明了:
2namespace 委托
3{
4 delegate int NumOpe(int a,int b); //委托声明
5 class Class1
6 {
7 static void Main(string[] args)
8 {
9 Class1 c1 = new Class1();
10 NumOpe p1 = new NumOpe(c1.Add); //委托实例化
11 Console.WriteLine(p1(1,2)); //委托调用
12 Console.ReadLine();
13 }
14 private int Add(int num1,int num2)
15 {
16 return(num1+num2);
17 }
18 }
19}
例中,委托NumOpe引用了方法Add。
委托声明了以后,就可以象类一样进行实例化,实例化时把要引用的方法(如:Add)做为参数,这样委托和方法就关联了起来,就可以用委托来引用方法了。
委托和所引用的方法必须保持一致:
1、参数个数、类型、顺序必须完全一致。
2、返回值必须一致。
二、委托的应用-事件
委托的一个最常用的应用就是事件。
事件和处理方法之间是怎么联系起来的呢?委托就是他们中间的桥梁,事件发生时,委托会知道,然后将事件传递给处理方法,处理方法进行相应处理。
比如在WinForm中最常见的是按钮的Click事件,它是这样委托的:
this.button1.Click += new System.EventHandler(this.button1_Click);
按按钮后就会出发button1_Click方法进行处理。EventHandler就是系统类库里已经声明的一个委托。
三、自定义事件及其处理
自定义事件是更委托的复杂的应用。
EventHandler以及其它自定义的事件委托都是一类特殊的委托,他们有相同的形式:
delegate void 事件委托名(object sender,EventArgs e);
object用来传递事件的发生者,比如二中的Button控件就是一个事件发生者;EventArgs用来传递事件的细节。
下面是两个例子:
例程二:
2namespace 最简单的自定义事件
3{
4 /// <summary>
5 /// 事件发送类
6 /// </summary>
7 class Class1
8 {
9 public delegate void UserRequest(object sender,EventArgs e); //定义委托
10 public event UserRequest OnUserRequest; //定义一个委托类型的事件
11 public void run()
12 {
13 while(true)
14 {
15 if(Console.ReadLine()=="a")
16 {//事件监听
17 OnUserRequest(this,new EventArgs()); //产生事件
18 }
19 }
20 }
21 }
22 /// <summary>
23 /// 事件接收类
24 /// </summary>
25 class Class2
26 {
27 static void Main(string[] args)
28 {
29 Class1 c1 = new Class1();
30 c1.OnUserRequest += new Class1.UserRequest(c1_OnUserRequest); //委托实例化后绑定到事件
31 c1.run();
32 }
33 private static void c1_OnUserRequest(object sender, EventArgs e)
34 {//事件处理方法
35 Console.WriteLine("\t你触发了事件!");
36 }
37 }
38}
例程三:
2namespace 带事件数据的事件
3{
4 /// <summary>
5 /// 带事件数据的事件类,从EventArgs继承
6 /// </summary>
7 class OnUserRequestEventArgs:EventArgs
8 {
9 private string inputText;
10 public string InputText
11 {
12 get
13 {
14 return inputText;
15 }
16 set
17 {
18 inputText = value;
19 }
20 }
21 }
22 /// <summary>
23 /// 事件发送类
24 /// </summary>
25 class Class1
26 {
27 public delegate void UserRequest(object sender,OnUserRequestEventArgs e);
28 public event UserRequest OnUserRequest;
29 public void run()
30 {
31 while(true)
32 {
33 Console.WriteLine("请输入内容:");
34 string a=Console.ReadLine();
35 //if(a=="a")
36 //{
37 OnUserRequestEventArgs e1 = new OnUserRequestEventArgs();
38 e1.InputText = a;
39 OnUserRequest(this,e1);
40 //}
41 }
42 }
43 }
44 /// <summary>
45 /// 事件接收类
46 /// </summary>
47 class Class2
48 {
49 [STAThread]
50 static void Main(string[] args)
51 {
52 Class1 c1 = new Class1();
53 c1.OnUserRequest += new Class1.UserRequest(c1_OnUserRequest);
54 c1.run();
55 }
56 private static void c1_OnUserRequest(object sender, OnUserRequestEventArgs e)
57 {
58 Console.WriteLine("\t你输入的是:"+e.InputText);
59 }
60 }
61}
- 当封装静态方法可取时。
- 当使用事件设计模式时。
- 当调用主不需要访问实现该方法的对象中的其他属性、方法或接口时
- 需要方便的组合时。
- 当类可能需要该方法的多个实现时。