c#中把委托的作用当作是给方法的签名(包括参数类型,个数,方法的返回类型)指定名称。委托代表了方法。
为什么说委托的类型是安全的:因为在定义委托的时候就指定了它所调用的方法的签名,所以在构造委托实例的时候会判断是否正确
2using System;
3
4namespace test1
5{
6 /// <summary>
7 /// Class1 的摘要说明。
8 /// </summary>
9
10 class MathsOperations
11 {
12 public static double multiplyByTwo(double value)
13 {
14 return value*2;
15 }
16
17 public static double Square(double value)
18 {
19 return value*value;
20 }
21 }
22
23 delegate double DoubleOp(double x);
24
25 class test1
26 {
27 static void Main()
28 {
29 DoubleOp[] operations =
30 {
31 new DoubleOp(MathsOperations.multiplyByTwo),
32 new DoubleOp(MathsOperations.Square)
33 };
34
35 for(int i=0;i<operations.Length;i++)
36 {
37 Console.WriteLine("Using operations[{0}];",i);
38 ProcessAndDisplayNumber(operations[i],2.0);
39 ProcessAndDisplayNumber(operations[i],5);
40 Console.WriteLine();
41 }
42 }
43
44 static void ProcessAndDisplayNumber(DoubleOp action,double value)
45 {
46 double result = action(value);
47 Console.WriteLine("Value is {0},result of operation is {1}",value,result);
48 }
49 }
50
51
52}
有些时候不用委托是很难实现某些功能的
1 class BubbleSorter
2 {
3 static public void Sort(object[] sortArray,CompareOp gtMethod)
4 {
5 for(int i=0;i<sortArray.Length;i++)
6 {
7 for(int j=i+i;i<sortArray.Length;j++)
8 {
9 if(gtMethod(sortArray[j],sortArray[i]))
10 {
11 object temp = sortArray[i];
12 sortArray[i] = sortArray[j];
13 sortArray[j] = temp;
14 }
15 }
16 }
17 }
18 }
19
20 delegate bool CompareOp(object lhs,object rhs);
21
22 class Employee
23 {
24 private string name;
25 private decimal salary;
26
27 public Employee(string name,decimal salary)
28 {
29 this.name=name;
30 this.salary=salary;
31 }
32 public override string ToString()
33 {
34 return string.Format(name + ",{0:c}",salary);
35 }
36 public static bool RhslsGreater(object lhs,object rhs)
37 {
38 Employee empLhs = (Employee)lhs;
39 Employee empRhs = (Employee)rhs;
40 return(empLhs.salary>empRhs.salary)?true:false;
41 }
42 }
43
44
45 class test1
46 {
47 static void Main()
48 {
49 Employee [] employees =
50 {
51 new Employee("abc",100),
52 new Employee("bbc",122),
53 new Employee("bb",111),
54 };
55
56
57 CompareOp employeeCompareOp = new CompareOp(Employee.RhslsGreater);
58 BubbleSorter.Sort(employees,employeeCompareOp);
59
60 for(int i=0;i<employees.Length;i++)
61 {
62 Console.WriteLine(employees[i].ToString());
63 }
64 }
65 }
66}
多播委托:委托包含多个方法。按顺序连续调用多个方法,委托的签名必须返回void(否则,返回值应送到何处)。实际上,如果编译器发现某个委托返回void,就会自动假定这是一个多播委托。2 {
3 static public void Sort(object[] sortArray,CompareOp gtMethod)
4 {
5 for(int i=0;i<sortArray.Length;i++)
6 {
7 for(int j=i+i;i<sortArray.Length;j++)
8 {
9 if(gtMethod(sortArray[j],sortArray[i]))
10 {
11 object temp = sortArray[i];
12 sortArray[i] = sortArray[j];
13 sortArray[j] = temp;
14 }
15 }
16 }
17 }
18 }
19
20 delegate bool CompareOp(object lhs,object rhs);
21
22 class Employee
23 {
24 private string name;
25 private decimal salary;
26
27 public Employee(string name,decimal salary)
28 {
29 this.name=name;
30 this.salary=salary;
31 }
32 public override string ToString()
33 {
34 return string.Format(name + ",{0:c}",salary);
35 }
36 public static bool RhslsGreater(object lhs,object rhs)
37 {
38 Employee empLhs = (Employee)lhs;
39 Employee empRhs = (Employee)rhs;
40 return(empLhs.salary>empRhs.salary)?true:false;
41 }
42 }
43
44
45 class test1
46 {
47 static void Main()
48 {
49 Employee [] employees =
50 {
51 new Employee("abc",100),
52 new Employee("bbc",122),
53 new Employee("bb",111),
54 };
55
56
57 CompareOp employeeCompareOp = new CompareOp(Employee.RhslsGreater);
58 BubbleSorter.Sort(employees,employeeCompareOp);
59
60 for(int i=0;i<employees.Length;i++)
61 {
62 Console.WriteLine(employees[i].ToString());
63 }
64 }
65 }
66}
例子:
1using System;
2
3namespace test1
4{
5 /// <summary>
6 /// Class1 的摘要说明。
7 ///</summary>
8
9 class MathsOperations
10 {
11 public static void multiplyByTwo(double value)
12 {
13 double result = value*2;
14 Console.WriteLine(
15 "Multiplying by 2:{0} gives {1}",value,result);
16 }
17
18 public static void Square(double value)
19 {
20 double result = value*value;
21 Console.WriteLine(
22 "Squareing:{0} gives {1}",value,result);
23 }
24 }
25
26 delegate void DoubleOp(double value);
27
28 class test1
29 {
30 static void Main()
31 {
32 //或,委托可以识别 +,+=,-,-=
33 //DoubleOp operations = new DoubleOp(MathsOperations.multiplyByTwo);
34 //operations += new DoubleOp(MathsOperations.Square);
35
36 DoubleOp opertaion1 = new DoubleOp(MathsOperations.multiplyByTwo);
37 DoubleOp operation2 = new DoubleOp(MathsOperations.Square);
38 DoubleOp operations = opertaion1 + operation2;
39
40 ProcessAndDisplayNumber(operations,2.0);
41 ProcessAndDisplayNumber(operations,40.0);
42 }
43
44 static void ProcessAndDisplayNumber(DoubleOp action,double value)
45 {
46 Console.WriteLine("\nProcessAndDisplay Number called with value = " +
47 value);
48 action(value);
49 }
50 }
51}
2
3namespace test1
4{
5 /// <summary>
6 /// Class1 的摘要说明。
7 ///</summary>
8
9 class MathsOperations
10 {
11 public static void multiplyByTwo(double value)
12 {
13 double result = value*2;
14 Console.WriteLine(
15 "Multiplying by 2:{0} gives {1}",value,result);
16 }
17
18 public static void Square(double value)
19 {
20 double result = value*value;
21 Console.WriteLine(
22 "Squareing:{0} gives {1}",value,result);
23 }
24 }
25
26 delegate void DoubleOp(double value);
27
28 class test1
29 {
30 static void Main()
31 {
32 //或,委托可以识别 +,+=,-,-=
33 //DoubleOp operations = new DoubleOp(MathsOperations.multiplyByTwo);
34 //operations += new DoubleOp(MathsOperations.Square);
35
36 DoubleOp opertaion1 = new DoubleOp(MathsOperations.multiplyByTwo);
37 DoubleOp operation2 = new DoubleOp(MathsOperations.Square);
38 DoubleOp operations = opertaion1 + operation2;
39
40 ProcessAndDisplayNumber(operations,2.0);
41 ProcessAndDisplayNumber(operations,40.0);
42 }
43
44 static void ProcessAndDisplayNumber(DoubleOp action,double value)
45 {
46 Console.WriteLine("\nProcessAndDisplay Number called with value = " +
47 value);
48 action(value);
49 }
50 }
51}
事件:事件与委托是密不可分的。
应用程序是通过windows来通信的,而windows又是使用预定义的消息与应用程序通信的。微软已经定义好了N多个系统事件(消息),譬如点击一个摁钮,打开一个下拉框,等等。事件接收器就是指发生某事件时被通知的任何应用程序,对象或组件。事件发送器可以是应用程序的一个对象或程序集。系统事件中如鼠标单击,键盘按键。.net程序中的事件发送器就是.net的运行库,.net framework把windows消息封装在了事件中,偶没学过windows编程,对windows消息的机制不甚了解。大概就是button的click事件封装了windows的WM_MOUSECLICK消息。然后就可以直接调用click事件了。
button1.click += new EventHandler(Button_Click);
事件 += 实例化一个委托(某个方法) //可多个方法依次添加到委托列表,但不能保证调用时方法的顺序。
EventHandler 委托在Farmework是已定义的,位于System命名空间,在所有的Farmework中的定义的事件都是用它。添加到该委托列表的方法都必须有相同的签名。private void Button_Click(object sender , Eventargs e) //1参:引发事件的对象,2参:包含有关事件的其他有用信息的对象,可任意类型,只要派生于它均可,譬如MouseDownEventArgs 类型。
委托和事件在用户界面程序里用的比较的多,比如象在winform或webform的用户UI上的button和它的click事件:
// 将Button1_Click()方法绑定到按钮控件Button1的Click事件上
this.Button1.Click += new System.EventHandler(this. Button1_Click);
private void Button1_Click(object sender, System.EventArgs e) // Button1_Click()方法
{
……
}
然而除了用户界面程序外,在很多其他地方也用到了事件驱动模式,比如观察者模式(Observer)或发布/订阅(Publish/Subscribe)里:在一个类里发布(Publish)某个可以被触发的事件,而其他的类就可以来订阅(Subscribe)该事件。一旦这个发布者类触发了该事件,那么运行时环境会立刻告知所有订阅了该事件的订阅者类:这个事件发生了!从而各个订阅者类可以作出它们自己的反应(调用相应方法)。