【从码农到程序员】使用委托让代码更优雅
很多繁杂的代码可以用委托去优雅的实现同样的功能。
委托:寻址方法的.NET版本,类似于C++中的指针,区别在于类型安全,定于的返回类型和参数类型。委托是对方法引用。
定义委托
两个string类型的参数、返回值为string类型
public delegate string GetString(string a,string b);
Action<T>和Func<T>委托
泛型Action<T>委托表示引用一个void返回类型的方法。
Func<T>允许调用带返回类型的方法。PS: Func<int,int,bool> 是引用一个带两个整型参数,返回布尔类型的方法
适合使用委托的情况
我们使用冒泡排序对一组int型值进行排序,代码如下
1 public static void Sort(int[] arr) 2 { 3 for (int i = 0; i < arr.Length - 1; i++) 4 { 5 for (int j = 0; j < arr.Length - 1 - i; j++) 6 { 7 if (arr[j] > arr[j + 1]) 8 { 9 int temp = arr[j]; 10 arr[j] = arr[j + 1]; 11 arr[j + 1] = temp; 12 } 13 } 14 } 15 }
但是如果我们希望Sort方法能给任何对象排序,目前的实现肯定无法满足。
比如一个Student对象,需要按照年龄排序
1 class Student 2 { 3 public Student(string name, int age) 4 { 5 this.Name = name; 6 this.Age = age; 7 } 8 9 public string Name { get; private set; } 10 public int Age { get; private set; } 11 12 public override string ToString() 13 { 14 return string.Format("{0}, {1}", Name, Age); 15 } 16 17 public static bool CompareAge(Student s1, Student s2)//年龄比较方法 18 { 19 return s1.Age < s2.Age; 20 } 21 }
可以将之扩展成一个泛型方法Sort<T>,需要有一个比较方法,比较两个T类型的参数,肯定不能使用“>”这种运算符去比较,这个方法可以Func<T1,T2,TResult>委托中引用,其中T1、T2的类型相同:Func<T,T,bool>
1 static public void Sort<T>(IList<T> sortArray, Func<T, T, bool> comparison) 2 { 3 4 for (int i = 0; i < sortArray.Count - 1; i++) 5 { 6 for (int j = 0; j < sortArray.Count - 1 - i; j++) 7 { 8 if (comparison(sortArray[j + 1], sortArray[j])) 9 { 10 T temp = sortArray[j]; 11 sortArray[j] = sortArray[j + 1]; 12 sortArray[j + 1] = temp; 13 } 14 } 15 } 16 17 }
测试调用方法:
1 Student[] students = { 2 new Student("Curry",34), 3 new Student("Lebron",23), 4 new Student("Kobe",24), 5 new Student("Yao",11) 6 }; 7 BubbleSorter.Sort(students, Student.CompareAge); 8 foreach (var student in students) 9 { 10 Console.WriteLine(student); 11 }
委托还可以引用多个方法(多播委托),但是需要注意的是,其中一个方法异常,整个迭代就会停止;
匿名方法是将方法体直接赋予委托的一种委托创建方式,从C#3.0开始,可以使用Lamda表达式代替匿名方法;
事件基于委托,为委托提供了一种发布/订阅机制