C#中的委托相当于C++中的函数指针。也就是可以拿来执行函数的东西,可以像使用变量一样使用函数。
可以实现类似的功能,但是更为的安全。
今天简单的写一些C#中委托的使用,多路广播,以及事件的概念和C#中事件机制的构建。
关于回调和异步调用设计到进程的东西就没有了。
委托是一种封装的方法类型。他是封闭的对象,所以是没法自己实例化的。所以只能通过特定的语法来定义。
语法如下
public delegate void output(string name);
定义了一个委托output。你可以把它指向具有相同函数签名的方法。
先贴一段代码
1: public delegate void output(string name);
2: class Program
3: {
4: public static void outputA(string name)
5: {
6: Console.WriteLine("A {0}", name);
7: }
8: static void Main(string[] args)
9: {
10: output o1;
11: o1 = outputA;
12: o1("Tom");
13: Console.ReadKey();
14: }
15: }
11行我们把一个委托实例o1指向一个方法。到此为止似乎都还看不出委托到底有什么用。
这里要留意一个东西委托实例指向的方法要和委托声明时的函数签名一样。但是也有一定得灵活性。允许指向函数的返回类型是委托定义返回类型的子类,指向函数的参数类型是委托定义参数类型的父类。具体可以参考C#中委托的协变与逆变。
这里主要是看一下委托的简单定义与使用。
下面来看多路广播的简单代码,就可以看出委托的一些特点
1: public delegate void output(string name);
2: class Program
3: {
4: public static void outputA(string name)
5: {
6: Console.WriteLine("A {0}",name);
7: }
8: public static void outputB(string name)
9: {
10: Console.WriteLine("B {0}", name);
11: }
12: static void Main(string[] args)
13: {
14: output o1;
15: o1 = outputA;
16: o1 += outputB;
17: o1("Tom");
18: o1 -= outputA;
19: o1("Tom");
20: Console.ReadKey();
21: }
22: }
从代码可以看书,一个委托不只可以指向一个方法,可以指向很多方法。这里应该称为注册,或者是说订阅。把方法注册到委托中。
这样可以一次性执行很多操作,这一点在事件机制中非常有用。可以让方法的编写与委托分开。
需要注意的是14行用的是=号,15行是需要用+=的。
还有一点是通常这个时候的委托定义都是没有返回值的,不然一次执行过个方法会不知道应该返回哪一个返回值。实际情况是他会返回最后执行的那个方法的返回值。
关于事件,事件是委托的一个封装。封装的内容包括委托的访问级别(现在只能设置为public很好),还有就是不用第一次使用=,后面使用+=。而是全部使用+=。
关于事件.Net Framework给了一个编码规范:
- 委托类型的名称都应该以EventHandler结束。
- 委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型,一个 EventArgs类型(或继承自EventArgs)。
- 事件的命名为 委托去掉 EventHandler之后剩余的部分。
- 继承自EventArgs的类型应该以EventArgs结尾。
我写了一段模拟事件处理的代码,设定了发布者CMD类有一个Input事件让用户输入,事件发生时检查一下有没有订阅这个事件的方法,有的话,把用户输入的内容发送给订阅者,让他进行处理。
这样我们就把事件处理的方法独立出来,并且可以随时简单的进行增减。
1: public class Cmd
2: {
3: public delegate void InputEventHandler(object sender, InputEventArgs e);
4: public event InputEventHandler Input;
5:
6: public class InputEventArgs : EventArgs
7: {
8: public string name;
9: public InputEventArgs (string name)
10: {
11: this.name = name;
12: }
13: }
14:
15: protected void OnInput(InputEventArgs e)
16: {
17: if (Input != null)
18: {
19: Input(this,e);
20: }
21: }
22:
23: public void run()
24: {
25: string name;
26: name = Console.ReadLine();
27: InputEventArgs e = new InputEventArgs(name);
28: OnInput(e);
29: }
30: }
31:
32: class Program
33: {
34: public static void output(object sender, Cmd.InputEventArgs e)
35: {
36: Console.WriteLine("output: {0}", e.name);
37: }
38: static void Main(string[] args)
39: {
40: Cmd c1 = new Cmd();
41: c1.Input += output;
42: c1.run();
43: Console.ReadKey();
44: }
45: }
解释一下关于编程规范的那些东西。其中object类型sender是事件发送的对象,InputEventArgs是一个继承自EventArgs的类专门用来包含关于事件所需要参数的类。
OnInput是用来处理事件方法。这里只是简单的检测有没有订阅者。
这篇文章写了很烂,很多东西都没能讲清楚,应该是自己的理解还是不够深刻。这也是为什么一直想要坚持写东西的原因,写东西能发现自己还有很多东西理解并不是很深刻。
不过下面有一些很不错的文章可以参考
http://www.7747.net/kf/201007/53018.html
http://wenku.baidu.com/view/181de1c5bb4cf7ec4afed035.html
http://www.cnblogs.com/michaelxu/archive/2008/03/31/1131500.html
http://www.cnblogs.com/michaelxu/archive/2008/04/02/1134217.html
http://www.cnblogs.com/jimmyzhang/archive/2007/09/23/903360.html
http://www.cnblogs.com/JimmyZhang/archive/2008/08/22/1274342.html
http://msdn.microsoft.com/zh-cn/library/ms173172%28v=VS.80%29.aspx
http://msdn.microsoft.com/zh-cn/library/ms173171.aspx
http://msdn.microsoft.com/zh-cn/library/ms173176%28v=VS.80%29.aspx
http://msdn.microsoft.com/zh-cn/library/ms173174%28v=VS.80%29.aspx