委托与事件
委托:譬如别人委托你买你去书挑选一本好的c#的书,而你却因为懒得动,直接去了dearbook选书,然后送上门。然后你转交给了朋友。这就是现实中的委托。-------你的好朋友并不知道,你没有去书店选。(不关注方法的细节)
c#中把委托的作用当作是给方法的签名(包括参数类型,个数,方法的返回类型)指定名称。委托代表了方法。
为什么说委托的类型是安全的:因为在定义委托的时候就指定了它所调用的方法的签名,所以在构造委托实例的时候会判断是否正确
2
using System;
3
4
namespace 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
}
有些时候不用委托是很难实现某些功能的
例子:
事件:事件与委托是密不可分的。
应用程序是通过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 类型。
c#中把委托的作用当作是给方法的签名(包括参数类型,个数,方法的返回类型)指定名称。委托代表了方法。
为什么说委托的类型是安全的:因为在定义委托的时候就指定了它所调用的方法的签名,所以在构造委托实例的时候会判断是否正确
2
using System;3

4
namespace test15
{6
/// <summary>7
/// Class1 的摘要说明。8
/// </summary>9
10
class MathsOperations11
{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 test126
{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,就会自动假定这是一个多播委托。
class BubbleSorter2
{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 Employee23
{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 test146
{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
}例子:
1
using System;
2
3
namespace 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
}
using System;2

3
namespace test14
{5
/// <summary>6
/// Class1 的摘要说明。7
///</summary>8
9
class MathsOperations10
{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 test129
{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)该事件。一旦这个发布者类触发了该事件,那么运行时环境会立刻告知所有订阅了该事件的订阅者类:这个事件发生了!从而各个订阅者类可以作出它们自己的反应(调用相应方法)。



浙公网安备 33010602011771号