浅谈C#委托的用法-delegate
2018年11月7日 小雨
一、委托的概念
-
委托和类一样是一种用户自定义类型,它存储的就是一系列具有相同签名和返回类型的方法的地址,调用委托的时候,它所包含的所有方法都会被执行。
-
借用百度上的一句话概括:委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,
可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。
二、委托的声明
与对应的方法具有相同的参数类型、参数个数、返回值。通俗来讲就是“函数的模板原型”。
三、委托的使用
- 用delegate声明一个委托
- 委托实例化
- 调用
1 public class DelegateClass 2 { 3 public delegate void DelegateTest(int a, int b); //1、声明一个委托 4 5 public static void Test() 6 { 7 DelegateTest method = new DelegateTest(Plus); //2、实例化委托 8 //DelegateTest method1 = Plus; //实例化委托的另一种等价写法 9 method.Invoke(1, 2); //3、调用 10 //method1(3, 4); //调用的另一种等价写法 11 } 12 13 private static void Plus(int a, int b) 14 { 15 Console.WriteLine("a={0} b={1}", a, b); 16 } 17 }
四、委托的意义
1、没有委托就没有异步
2、解耦
3、高效扩展
1 public class CallStudent 2 { 3 //方法1 4 public static void CallStudentA(string name) 5 { 6 Console.WriteLine("{0}", name); 7 } 8 //方法2 9 public static void CallStudentB(string name) 10 { 11 Console.WriteLine("{0}", name); 12 } 13 //方法3 14 public static void CallStudentC(string name) 15 { 16 Console.WriteLine("{0}", name); 17 } 18 19 //传值的方式,根据值来决定行为,所有的方法全部耦合在一起, 20 //如果要增加方法则需要修改该方法,不便于方法的封装、扩展 21 public static void CallStudentName(string name, StudentType type) 22 { 23 if (type == StudentType.A) 24 { 25 Console.WriteLine("{0}", name); 26 } 27 else if (type == StudentType.B) 28 { 29 Console.WriteLine("{0}", name); 30 } 31 else if (type == StudentType.C) 32 { 33 Console.WriteLine("{0}", name); 34 } 35 } 36 37 //用委托的方式来实现传递方法,如果要增加方法,只需要重新增加一个方法就好 38 public static void CallStudentName(string name, CallStudentHandler handler) 39 { 40 handler.Invoke(name); 41 } 42 } 43 44 public delegate void CallStudentHandler(string name); 45 46 public enum StudentType 47 { 48 A, 49 B, 50 C 51 }
1 static void Main(string[] args) 2 { 3 //用不同的值来区分不同的方法 4 CallStudent.CallStudentName("Student A",StudentType.A ); 5 CallStudent.CallStudentName("Student B", StudentType.B); 6 CallStudent.CallStudentName("Student C", StudentType.C ); 7 Console.WriteLine(); 8 9 //用委托的方式传递多个方法 10 CallStudentHandler handlerA = new CallStudentHandler(CallStudent.CallStudentA); 11 CallStudent.CallStudentName("Student A", handlerA); 12 13 CallStudentHandler handlerB = new CallStudentHandler(CallStudent.CallStudentB); 14 CallStudent.CallStudentName("Student B", handlerB); 15 16 CallStudentHandler handlerC = new CallStudentHandler(CallStudent.CallStudentC); 17 CallStudent.CallStudentName("Student C", handlerC); 18 Console.WriteLine(); 19 20 //用匿名函数的方法替代上述写法 21 CallStudentHandler handler1 = new CallStudentHandler( 22 delegate(string name) 23 { 24 Console.WriteLine("{0}", name); 25 }); //用匿名的方式把方法名给去掉 26 handler1.Invoke("Student A"); 27 28 //用lambda表达式的方式1 替代上述写法 29 //Lambda表达式的本质就是一个匿名方法 30 CallStudentHandler handler2= new CallStudentHandler( 31 (string name)=> 32 { 33 Console.WriteLine("{0}", name); 34 }); //用lambda表达式的方式把delegate换成=> 箭头左边是参数列表,右边是方法体 35 handler2.Invoke("Student A"); 36 37 //用lambda表达式的方式2 38 CallStudentHandler handler3 = new CallStudentHandler( 39 (name) => 40 { 41 Console.WriteLine("{0}", name); 42 }); //去掉参数类型 43 handler3.Invoke("Student A"); 44 45 //用lambda表达式的方式3 46 CallStudentHandler handler4 =(name) => 47 { 48 Console.WriteLine("{0}", name); 49 }; //去掉 new CallStudentHandler 50 handler4.Invoke("Student A"); 51 52 //用lambda表达式的方式4 53 CallStudentHandler handler5 = (name) => Console.WriteLine("{0}", name); //去掉{},适用于方法体只有一行 54 //去掉{}后,如果方法体只有一行,带返回值的去掉return 55 handler5.Invoke("Student A"); 56 57 Console.ReadLine(); 58 }