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