delegate是C#中的关键字,它的作用是啥,去网上搜会出现一堆晦涩难懂的描述,看的人头疼。本人初学C#,懂C语言,搞懂delegate之后我发现它不就是个函数指针吗!!!
C语言的函数指针
先看看C语言里的函数指针是怎么用的,如果我们想定义一个具有一个int类型返回值,并且有两个int类型的参数的函数指针,我们会这样写:
typedef int (*func)(int, int);
这时可以用func去定义函数指针,举例:
1 #include <stdio.h> 2 3 typedef int (*func)(int, int); 4 5 int add(int a, int b) 6 { 7 return a + b; 8 } 9 10 int main(int argc, const char *argv[]) 11 { 12 func p; 13 14 p = add; 15 16 printf("p(3, 4) = %d\n", p(3, 4)); 17 return 0; 18 }
执行结果:
C#中的delegate
C#中用delegate声明一个委托,用法如下:
delegate int Method(int a1, int a2);
其实这一句和C语言中的 typedef int (*func)(int, int); 作用如出一辙,写了这一句之后就可以用Method去定义一个类似于C语言函数指针的东西。测试代码如下:
1 using System; 2 3 namespace Test 4 { 5 class Test 6 { 7 delegate int Method(int a1, int a2); 8 9 static int add(int a, int b) 10 { 11 return a + b; 12 } 13 14 static void Main(string[] args) 15 { 16 Method p; 17 18 p = add; 19 20 Console.WriteLine("p(3, 4) = {0}", p(3, 4)); 21 Console.ReadKey(); 22 } 23 } 24 }
执行结果:
它也可以和C语言的函数指针一样,用不同的函数指针去赋值,测试代码如下:
1 using System; 2 3 namespace Test 4 { 5 class Test 6 { 7 delegate int Method(int a1, int a2); 8 9 static int add(int a, int b) 10 { 11 return a + b; 12 } 13 14 static int sub(int a, int b) 15 { 16 return a - b; 17 } 18 19 static void Main(string[] args) 20 { 21 Method p; 22 23 p = add; 24 Console.WriteLine("p(3, 4) = {0}", p(3, 4)); 25 p = sub; 26 Console.WriteLine("p(3, 4) = {0}", p(3, 4)); 27 28 Console.ReadKey(); 29 } 30 } 31 }
执行结果:
可以用new去给Method定义的变量赋值,也可以赋值为null,比如下面两句这样写是可以的,如果赋值为null,它就相当于C语言里的空指针,是不能拿去调用的。
Method p = new Method(add); Method q = null;
delegate多播
delegate还有和C语言不一样的地方,如下面这个程序:
1 using System; 2 3 namespace Test 4 { 5 class Test 6 { 7 delegate int Method(int a1, int a2); 8 9 static int add(int a, int b) 10 { 11 Console.WriteLine($"add({a}, {b}) = {a+b}"); 12 return a + b; 13 } 14 15 static int sub(int a, int b) 16 { 17 Console.WriteLine($"sub({a}, {b}) = {a-b}"); 18 return a - b; 19 } 20 21 static void Main(string[] args) 22 { 23 Method p = add; 24 p += sub; 25 26 Console.WriteLine("p(3, 4) = {0}", p(3, 4)); 27 28 Console.ReadKey(); 29 } 30 } 31 }
如果用C语言的思维去看第23行和第24行,在第23行已经给p赋值为add了,然后在第24行让它加上sub是什么意思,两个函数指针能相加吗?第26行代码的输出结果又会是什么呢?看看程序的执行结果吧:
结果表明,p先执行了add,再执行了sub,p的返回值是sub的返回值。这种用法其实是将方法加到队列之后,委托的执行过程与加入队列的顺序一致,委托执行的返回值是最后一个加入队列的方法的返回值。甚至这样写都没问题:
Method p = add; p += sub; p += add; p += sub; Console.WriteLine("p(3, 4) = {0}", p(3, 4));
执行结果如下:
委托不但可以加,还可以减,如果队列里没有要减去的方法,那就不会减了,比如下面这种写法:
Method p = add; p -= sub; Console.WriteLine("p(3, 4) = {0}", p(3, 4));
p里面只有add,若要让它减去sub那肯定是减不了的,不过程序执行并不会出错,最后的运行结果是只运行add。
那委托中减的顺序是怎样的呢?看下面这段代码:
1 Method p = add; 2 p += sub; 3 p += add; 4 p += sub; 5 6 p -= sub; 7 Console.WriteLine("p(3, 4) = {0}", p(3, 4));
执行结果:
如果将上面代码块第6行的sub换成add,那么执行结果是:
这两个例子表明,委托中减的顺序是从队列的最后面开始的。