使用c#委托

很多繁杂的代码可以用委托去优雅的实现同样的功能。

委托:寻址方法的.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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void Sort(int[] arr)
{
for (int i = 0; i < arr.Length - 1; i++)
{
for (int j = 0; j < arr.Length - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}

但是如果我们希望Sort方法能给任何对象排序,目前的实现肯定无法满足。

比如一个Student对象,需要按照年龄排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class 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
17
static 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
11
Student[] 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表达式代替匿名方法;

事件基于委托,为委托提供了一种发布/订阅机制