一、什么叫做将方法作为方法的参数?
我在查阅很多关于委托的资料的时候,都会看到这么一句话:将方法作为方法的参数。但是这句话的含义究竟是什么?他存在的意义在哪里呢?
我们先来看一个例子
首先定义两个方法:GreetPeople和EnglishGreeting,第一个方法用于向某人问好,传进去姓名的参数比如“Celine”,在这个方法中会调用EnglishGreeting的方法,再次传递“Celine”,最后向屏幕输出“Morning,Celine”
public void GreetPeople(string name)
{
EnglishGreeting(name);
}
public void EnglishGreeting(string name)
{
Console.WriteLine("Morning," + name);
}
这是中国人表示看不懂,不明白什么是Morning,所以,我们又加入了使用中文打招呼的方法
public void ChineseGreeting(string name)
{
Console.WriteLine("Morning," + name);
}
加入这个方法后,客户端也要做相应的修改,因为要根据不同的人,来选择不同的打招呼的方法。这是最好使用枚举来定义语言的种类,然后使用switch case带来进行选择。还记得吗?上一篇中,我们讨论过枚举。
public enum Language {
English,Chinese
}
public void GreetPeople(string name,Language lang)
{
switch(lang){
case Language.English:
EnglishGreeting(name);
break;
case Language.Chinese:
ChineseGreeting(name);
break;
}
}
这样就实现了中国人也能看懂的“早上好”,如果在来一个日本人怎么办?再添加一个JanpenesGreeting,然后在GreetPeople里边继续加新的选择分支,而且还要修改枚举类,可以说扩展起来非常麻烦,牵一发而动全身。
好了,饶了一个大圈,我们最初的问题是什么?把方法当做方法的参数,叮!有没有什么灵感闪现~
让我们再来看看GreetPeople这个方法,参数接收的是两个变量,一个是姓名一个是国家,假如我们让GeetPeople接收一个参数,而这个参数是另外一个方法,例如我们把EnglishGreeting这个方法当做参数传进去,或者如果你想要传ChineseGreeting,也完全可以,这样我们不就可以把switch case给去掉了吗?
顺着这个思路,我们写出来下边这个方法,MakeGreeting代表各种不同的语言打招呼的方法,***是代表数据类型的替换符,我们姑且写成下边这个样子
public void GreetPeople(string name,*** MakeGreeting)
{
MakeGreeting(name);
}
那么问题来了,这个传进去的方法参数MakeGreeting到底是什么参数类型呢??上边这个方法里边已经清楚的去掉了switch case,其实我们也不再需要枚举了,使用枚举只是为了条件选择的方便,当我们传进去MakeGreeting的时候,已经动态的进行了语言的选择
终于到了委托登场的时候了!我们使用委托来定义MakeGreeting参数所能代表的方法的种类,也就是MakeGreeting参数的类型,下边就是委托的定义,使用delegate关键字
public delegate void GreetingDelegate(string name);
我们再次定义GreetPeople方法
public void GreetPeople(string name,GreetingDelegate MakeGreeting)
{
MakeGreeting(name);
}
我们在把最初的方法粘过来对比一下
public void GreetPeople(string name,Language lang)
{}
委托的位置其实和枚举类型或者string类型处于相同的位置,string和枚举都是一种类型,那么委托也是一种类型吗??但是委托的声明和类完全不同。
实际上,委托在编译的时候确实会被编译成类,因为delegate是一个类,所以在任何可以声明类的地方都可以声明委托
现在让我们看看完整的代码:
namespace 委托DEMO
{
public delegate void GreetingDelegate(string name);
class Program
{
private static void GreetPeople(string name,GreetingDelegate MakeGreeting)
{
MakeGreeting(name);
}
private static void EnglishGreeting(string name)
{
Console.WriteLine("Morning," + name);
}
private static void ChineseGreeting(string name)
{
Console.WriteLine("你好," + name);
}
static void Main(string[] args)
{
GreetPeople("Celine", EnglishGreeting);
GreetPeople("陈丹", ChineseGreeting);
Console.ReadKey();
}
}
}
总结
委托是一个类,它定义了方法的类型,使得可以将方法当做另一个方法的参数来进行传递,这种讲方法动态地赋给参数的做法,可以避免在程序中大量使用IF-ELSE(SWITCH)语句,同时使程序具有更好的扩展性