前言:
C#委托是什么
c#中的委托可以理解为函数的一个包装, 它使得C#中的函数可以作为参数来被传递, 这在作用上相当于C++中的函数指针. C++用函数指针获取函数的入口地址, 然后通过这个指针来实现对函数的操作.
委托的定义和方法的定义类似, 只是在定义的前面多了一个delegate关键字.
正文:
委托可以被视为一个更高级的指针,它不仅仅能把地址传指向另一个函数,而且还能传递参数,返回值等多个信息。 系统还为委托对象自动生成了同步,异步的调用方式,开发人员使用BeginInvoke,EndInvoke方法就可以抛开Thread而直接使用多线程调用。
一, 委托 用IL 分析可看出Delegate继承自System.MulticastDelegate类,并自动生成BeginInvoke,EndInvoke,Invoke三种常见的方法。
Invoke方法是用于同步调用委托对象的对应方法,而BeginInvoke,EndInvoke是用于以异步方式调用对应方法的。
1.1 简单的委托 当建立委托对象时,委托的参数类型必须与委托方法相对应。只要向建立委托对象的构造函数中输入方法名称example.Method,委托就会直
接绑定此方法。 使用myDelegate.Invoke(string message),就能显式调用委托方法。 但在实际的操作中,我们无须用到 Invoke 方法,而只要直接使用myDelegate(string message),就能调用委托方法。
1 class Program
2 {
3 void MyDelegate(string message);
4
5 public class Example
6 {
7 public void Method(string message)
8 {
9 MessageBox.Show(message);
10 }
11 }
12
13 static void Main(string[] args)
14 {
15 Example example=new Example();
16 MyDelegate myDelegate=new MyDelegate(example.Method);
17 myDelegate("Hello World");
18 Console.ReadKey();
19 }
20 }
1.2 带返回值的委托
当建立委托对象时,委托的返回值必须与委托方法相对应。使用下面的例子,方法将返回 “Hello Leslie” 。
1 class Program
2 {
3 delegate string MyDelegate(string message);
4
5 public class Example
6 {
7 public string Method(string name)
8 {
9 return "Hello " + name;
10 }
11 }
12
13 static void Main(string[] args)
14 {
15 Example example=new Example();
16 //绑定委托方法
17 MyDelegate myDelegate=new MyDelegate(example.Method);
18 //调用委托,获取返回值
19 string message = myDelegate("Leslie");
20 Console.WriteLine(message);
21 Console.ReadKey();
22 }
23 }
1.3 多路广播委托 在上面提过,委托类继承于MulticastDelegate,这使委托对象支持多路广播,即委托对象可以绑定多个方法。 当输入参数后,每个方法会按顺序进行迭代处理,并返回最后一个方法的计算结果。 下面的例子中,Price 类中有两个计算方法,Ordinary 按普通的9.5折计算,Favourable 按优惠价 8.5 折计算。 委托同时绑定了这两个方法,在输入参数100以后,Ordinary、Favourable这两个方法将按顺序迭代执行下去,最后返回 Favourable 方法的
计算结果 85。
1 delegate double MyDelegate(double message);
2 public class Price
3 {
4 public double Ordinary(double price)
5 {
6 double price1 = 0.95 * price;
7 Console.WriteLine("Ordinary Price : "+price1);
8 return price1;
9 }
10
11 public double Favourable(double price)
12 {
13 double price1 = 0.85 * price;
14 Console.WriteLine("Favourable Price : " + price1);
15 return price1;
16 }
17
18 static void Main(string[] args)
19 {
20 Price price = new Price();
21 //绑定Ordinary方法
22 MyDelegate myDelegate = new MyDelegate(price.Ordinary);
23 //绑定Favourable方法
24 myDelegate += new MyDelegate(price.Favourable);
25 //调用委托
26 Console.WriteLine("Current Price : " + myDelegate(100));
27 Console.ReadKey();
28 }
29 }
1.4 Observer模式中的事件与委托
1 class Program
2 {
3 public delegate void ObserverDelegate();
4
5 static void Main(string[] args)
6 {
7 // 具体主题角色通常用具体自来来实现
8 ConcreteSubject subject = new ConcreteSubject();
9
10 //传入的只是观察者的通过方法。
11 subject.Attach(new ConcreteObserver(subject, "Observer A").Update);
12 subject.Attach(new ConcreteObserver(subject, "Observer B").Update);
13 subject.Attach(new ConcreteObserver(subject, "Observer C").Update);
14
15 subject.SubjectState = "Ready";
16 subject.Notify();
17
18 Console.Read();
19 }
20
21
22 //抽象主体类
23 public abstract class Subject
24 {
25 public ObserverDelegate observerDelegate;
26
27 //增加观察者
28 public void Attach(ObserverDelegate observer)
29 {
30 observerDelegate += observer;
31 }
32
33 //移除观察者
34 public void Remove(ObserverDelegate observer)
35 {
36 observerDelegate -= observer;
37 }
38
39 //像观察者发通知
40 public void Notify()
41 {
42 if (observerDelegate != null)
43 {
44 observerDelegate();
45 }
46 }
47 }
48
49 //具体主题类
50 public class ConcreteSubject : Subject
51 {
52 public string SubjectState { get; set; }
53 }
54
55 //具体观察者
56 public class ConcreteObserver
57 {
58 private string observerState;
59 private string name;
60 private ConcreteSubject subject;
61
62 public ConcreteObserver(ConcreteSubject subject, string name)
63 {
64 this.subject = subject;
65 this.name = name;
66 }
67
68 //实现抽象观察者中的更新操作
69 public void Update()
70 {
71 observerState = subject.SubjectState;
72 Console.WriteLine("The observer's state of {0} is {1}", name, observerState);
73 }
74 }
75 }
二,事件 event
(1) 事件时委托的封装,可以理解为一种特殊的委托。 (2) 事件里面其实就两个方法(即add_event() 和 remove_event())和一个私有的委托变量,这两个方法里面分别是对这个私有的委托变量进
行的合并和移除,当调用事件的+=时其实是调用的事件里的add_event()方法,同样-=调用的是remove_event()方法 (3) 事件只能够从对象外部增加新的响应方法和删除已知的响应方法,而不能主动去触发事件和获取其他注册的响应方法等信息。如果使用
公有的delegate则不能做这些限制,也就是说事件对委托做了限制,使委托使用起来更加方便。 也有人说事件是对委托的阉割,大概也是这个意思。
这里事件没有做过多的阐述, 看到一个关于事件讲解的比较不错的博文, 推荐大家看下吧: http://www.cnblogs.com/landeanfen/p/4721525.html
PS: 本博客只是为了记录自己学习中的收获, 俗话说 好记性不如烂笔头. 望自己能够坚持下去.