委托和类、结构、接口、枚举都可以看成是类型
类是对现实生活中的对象的抽象实现(比如人,都具有相同特性——眼睛,鼻子,耳朵),而委托是对函数的抽象实现(比如两个函数,输入参数类型和数量相同,返回值也相同,同时完成相同的功能)
举例:
delegate int GetCalculatedValueDelegate(int x, int y);
static int AddCalculator(int x, int y)
{
return x + y;
}
static int SubCalculator(int x, int y)
{
return x - y;
}
static void Main(string[] args)
{
GetCalculatedValueDelegate d = AddCalculator;
Console.WriteLine(d(10, 20));
}
本来需要让AddCalculator调用的,结果GetCalculatedValueDelegate(d)把这个事个做了。本来是要小明去老师办公室拿粉笔盒的,由于小明和小文是好朋友,因此小明就要小文代他去拿,于是小文成了小明的代理,小明委托小文去拿粉笔盒
委托作为参数:
delegate int GetCalculatedValueDelegate(int x, int y);
static int AddCalculator(int x, int y)
{
return x + y;
}
static int SubCalculator(int x, int y)
{
return x - y;
}
static int Calculator(GetCalculatedValueDelegate del, int x, int y)
{
return del(x, y);
}
static void Main(string[] args)
{
Console.WriteLine(Calculator(AddCalculator, 10, 20));
}
这个和模板模式差不多。在模板方法模式中,可以将可变的部分留给子类去重写,而将不变的部分由父类实现
那么在委托作为参数的情况下,Calculator可以自己处理不变的逻辑,而将“具体怎么做”的事情委托给他人去办理。
委托作为参数,在C#中非常常见。比如线程的创建,需要给一个ThreadStart或者ParameterizedThreadStart委托作为参数,而在线程执行的时候,将这个参数所指代的函数用作线程执行体。再比如:List<T>类型的Find方法的参数也是一个委托,它把“怎么去查找”或者说“怎么样才算找到”这个问题留给了开发人员。开发人员只需要定义一个参数为T,返回值为布尔型的函数,实现函数体,并将函数作为参数传给Find方法,就可以完成集合中元素的查找。
委托作为返回值一般会用在“根据不同情况决定使用不同的委托”这样的情形下。这有点像工厂模式,不过委托用作返回值还是用的没有用作参数这样频繁。
与委托相关的概念还有很多,比如异步调用、泛型委托、匿名方法、Lambda表达式、事件、协变与逆变等。我会在后续的文章中陆续介绍。