这一周章老师又讲授了许多知识,本次学习记录就主要探究我非常感兴趣的委托机制。
delegate是表示对具有特定参数列表和返回类型的方法的引用的类型。 在实例化委托时,我们可以将其实例与任何具有兼容签名和返回类型的方法相关联。 我们可以通过委托实例调用方法。委托用于将方法作为参数传递给其他方法。 事件处理程序就是通过委托调用的方法。 我们可以创建一个自定义方法,当发生特定事件时,某个类(如 Windows 控件)就可以调用我们的方法。它其实类似于C++中指向函数指针。一个委托声明示例演示如下:
1 public delegate int Sample( int x, int y );
可将任何可访问类或结构中与委托类型匹配的任何方法分配给委托。 该方法可以是静态方法,也可以是实例方法。 这样便能通过编程方式来更改方法调用,还可以向现有类中插入新代码。
下面附上一个委托应用实例:
1 //定义delegate方法Sample的返回值和签名 2 delegate int Sample(int x, int y); 3 4 class Class2 5 { 6 public int method(int x, int y) 7 { return x * y; } 8 } 9 10 class Class1 11 { 12 static void Main(string[] args) 13 { 14 Class2 instance = new Class2(); 15 //将method方法作为参数传给Sample 16 Sample mySample 17 = new Sample(instance.method); 18 int result = mySample(2, 3); 19 Console.WriteLine(result); 20 Console.ReadKey(); 21 } 22 }
从上面的实例可以看出,使用method方法作为参数调用Sample的构造函数生成对象,之后mysample便可直接传入参数调用method。
下面展示一个完整的实例:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace delegateTest 8 { 9 using System; 10 using System.Collections.Generic; 11 using System.Text; 12 13 namespace Delegate 14 { 15 //定义委托,它定义了可以代表的方法的类型 16 public delegate void GreetingDelegate(string name); 17 class Program 18 { 19 20 private static void EnglishGreeting(string name) 21 { 22 Console.WriteLine("Morning, " + name); 23 } 24 25 private static void ChineseGreeting(string name) 26 { 27 Console.WriteLine("早上好, " + name); 28 } 29 30 //此方法接受一个GreetingDelegate类型的方法作为参数 31 private static void GreetPeople(string name, GreetingDelegate MakeGreeting) 32 { 33 MakeGreeting(name); 34 } 35 36 static void Main(string[] args) 37 { 38 GreetPeople("Jack", EnglishGreeting); 39 GreetPeople("杰克", ChineseGreeting); 40 Console.ReadKey(); 41 } 42 } 43 } 44 45 46 }
输出如下
可以看出,GreetPeople方法是对不同的参数返回不同结果的简单实现,避免了大量if,else的使用,根据第二个参数的不同可以调用不同的方法轻松实现不同的问候方式。
因为委托GreetingDelegate 和 类型 string 的地位一样,都是定义了一种参数类型,那么,我们也可以这么使用委托:
1 static void Main(string[] args) { 2 GreetingDelegate delegate1, delegate2; 3 delegate1 = EnglishGreeting; 4 delegate2 = ChineseGreeting; 5 6 GreetPeople("Jack", delegate1); 7 GreetPeople("杰克", delegate2); 8 Console.ReadKey(); 9 }
输出与原来是相同的。
但是委托有不同于string的一个特性:可以将多个方法赋给同一个委托,或者叫将多个方法绑定到同一个委托,当调用这个委托的时候,将依次调用其所绑定的方法。示例如下:
1 static void Main(string[] args) { 2 GreetingDelegate delegate1; 3 delegate1 = EnglishGreeting; // 先给委托类型的变量赋值 4 delegate1 += ChineseGreeting; // 给此委托变量再绑定一个方法 5 6 // 将先后调用 EnglishGreeting 与 ChineseGreeting 方法 7 GreetPeople("Jack", delegate1); 8 Console.ReadKey(); 9 }
输出如下:
实际上,我们可以也可以绕过GreetPeople方法,通过委托来直接调用EnglishGreeting和ChineseGreeting:
1 static void Main(string[] args) { 2 GreetingDelegate delegate1; 3 delegate1 = EnglishGreeting; // 先给委托类型的变量赋值 4 delegate1 += ChineseGreeting; // 给此委托变量再绑定一个方法 5 6 // 将先后调用 EnglishGreeting 与 ChineseGreeting 方法 7 delegate1 ("Jack"); 8 Console.ReadKey(); 9 }
输出与上面相同。
委托可以绑定一个方法,那么也应该有办法取消对方法的绑定,很容易想到,这个语法是“-=”:
1 static void Main(string[] args) { 2 GreetingDelegate delegate1 = new GreetingDelegate(EnglishGreeting); 3 delegate1 += ChineseGreeting; // 给此委托变量再绑定一个方法 4 5 // 将先后调用 EnglishGreeting 与 ChineseGreeting 方法 6 GreetPeople("Jack", delegate1); 7 Console.WriteLine(); 8 9 delegate1 -= EnglishGreeting; //取消对EnglishGreeting方法的绑定 10 // 将仅调用 ChineseGreeting 11 GreetPeople("杰克", delegate1); 12 Console.ReadKey(); 13 }
输出如下:
同时注意到,这次我用了EnglishGreeting方法初始化了GreetingDelegate,也是可行的,效果相同。
我现在对委托做一个总结:
委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。
委托具有以下属性:
-
委托类似于 C++ 函数指针,但它们是类型安全的。
-
委托允许将方法作为参数进行传递。
-
委托可用于定义回调方法。
-
委托可以链接在一起;例如,可以对一个事件调用多个方法。
-
方法不必与委托类型完全匹配。
本次学习记录到此为止。请各位老师大牛不吝赐教!