C#委托详解(2):实现方式大全
本系列文章将详细探讨C#中的委托,列举其主要的实现方式,并分析其在设计层面和编码层面带来的好处,最后会讨论其安全性和执行效率等。
接上篇(C#委托详解(1):什么是委托)介绍完什么是委托之后,来看看C#中实现委托有哪些方式及各自主要适用范围。
1、常规实现
private delegate String getAString(); static void Main(String []args) { int temp = 40; getAString stringMethod = new getAString(temp.ToString); Console.WriteLine("String is {0}", stringMethod());//这里stringMethod()等价于调用temp.ToString(); Console.ReadLine(); }
这段代码中,实例化了类型为GetAString的一个委托,并对它进行初始化,使它引用整型变量temp的ToString()方法。在C#中,委托在语法上总是接受一个参数的构造函数,这个参数就是委托引用的方法。上例中stringMethod()等价于使用temp.ToString(),同时也与调用委托类的Invoke()方法完全相同,实际上,如下图IL代码中红色部分所示,C#编译器会用stringMethod.Invoke()代替stringMethod()。
为了简便输入,C#支持只传送地址的名称给委托的实例(委托推断),如下两行代码在编译器看来是一样的。
getAString stringMethod = new getAString(temp.ToString); getAString stringMethod = temp.ToString;
实际上委托的实例可以引用任何类型的任何对象上的实例方法或静态方法,只要方法的签名匹配于委托的签名即可。所以结构体的方法一样可以传递给委托。
2、多播委托
多播委托具有一个带有链接的委托列表,称为调用列表,在对委托实例进行调用的时候,将按列表中的委托顺序进行同步调用。如果委托有返回值,则将列表中最后一个方法的返回值用作整个委托调用的返回值。因此,使用多播委托通常具有void返回类型。
可以使用+=来使委托指向多个方法的地址,但必须是在委托实例化之后才可以使用+=来添加新的方法地址(添加重复的方法地址编译器不会报错,但是也不会重复执行),若想移除其中的方法地址可以使用-=来实现(需要至少保留一个,即对于最后一个方法地址的移除不起作用)。以下代码中下面两行无论单独保留哪行,最终的执行结果都是相同的。
getAString stringMethod = new getAString(temp.ToString); stringMethod += temp.ToString; stringMethod -= temp.ToString;
3、委托数组
delegate double Operations(double x); class Program { static void Main() { Operations[] operations = { MathOperations.MultiplyByTwo, MathOperations.Square }; for (int i = 0; i < operations.Length; i++) { Console.WriteLine("Using operations[{0}]:", i); DisplayNumber(operations[i], 2.0); DisplayNumber(operations[i], 7.94); Console.ReadLine(); } } static void DisplayNumber(Operations action, double value) { double result = action(value); Console.WriteLine( "Input Value is {0}, result of operation is {1}", value, result); } } struct MathOperations { public static double MultiplyByTwo(double value) { return value * 2; } public static double Square(double value) { return value * value; } }
上述代码中实例化了一个委托数组operations(与处理类的实例相同),该数组的元素初始化为MathOperations类的不同操作,遍历这个数组,可以将每个操作应用到2个不同的值中。这种用法的好处是,可以在循环中调用不同的方法。
(不早了,今天先写到这,下一篇接着写委托的实现方式。)