c#之委托详解(Delegate)
一、委托的概念
在我们学习委托之前,我们来了解下,什么是委托呢?
官方概念:委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似。与 C 中的函数指针不同,委托是面向对象的、类型安全的和保险的。委托的类型由委托的名称定义。
很多初学者都看不懂官方的概念,一脸懵逼。
举个例子吧:有几个小伙伴在外面玩,突然有两个人手机忘记带了,并且两个人家距离很近,其中一个人想要骑车回去拿,另一个不想回去,就委托另一个帮他拿。
其实委托就是一个类型,它所实例化的变量就是委托类型的变量,也可以说委托是一个方法的模板,当我们去掉delegate关键字的时候,就像是一个没有方法体的方法。
二、委托声明语法
delegate <return type> <delegate-name> <parameter list>
三、接下来我们来看下委托三部曲
public class MyDelegate
{
////1、委托的声明
public delegate void NoReturnNopara();
public static void show()
{
//2、委托的实例化
NoReturnNopara method = new NoReturnNopara(Study);
//3、委托的调用
method.Invoke();
}
public static void Study()
{
Console.WriteLine("正在学习delegate!");
}
}
然后我们调用show方法来看一个结果:
结果没毛病。
四、委托的用途
接下来我们来思考下,这样用委托有什么意义呢?还不如直接 MyDelegate.Study(); 这样。
当然我们学习委托并不是简单的像上面一样,上面只是为了便于我们学习了解委托而已。接下来我们来看一个打招呼的例子:
public class MyGreeting
{
public static void GreetingChinese(string name)
{
Console.WriteLine("{0},早上好",name);
}
public static void GreetingEnglish(string name)
{
Console.WriteLine("{0},good morning",name);
}
}
上面是中国人和外国人打招呼的方式,那个问题来了,我们怎么确定打招呼的人是中国人还中外国人呢?简单,我们定义一个枚举然后判断一个不就ok了嘛。
public class MyGreeting
{public static void Greeting(string name,PeopleType type)
{
switch (type)
{
case PeopleType.Chinese: Console.WriteLine("{0},早上好", name);
break;
case PeopleType.English: Console.WriteLine("{0},good morning", name);
break;
}
}
}
public enum PeopleType
{
Chinese,
English
}
这种做法满足了我们的需求。但是我们应该有所发现,这个方法的可扩展性很差,日后我们要是又有一个需求,要添加日本人打招呼,韩国人打招呼怎么办?我们就不得不修改枚举和Greeting这个方法内的代码,真是糟糕逶了。
那么,我们就应该想其它的方法来解决这个问题。从而达到”对扩展开方,对修改封闭“的原则。怎么实现呢?我们可以不管是哪国人,只负责打招呼就好,将打招呼的逻辑做为参数。
首先,我们先定义一个打招呼的委托。
public delegate void DeleGreeting(string name);
然后将这个委托做为参数传给 Greeting(string name,DeleGreeting greeting) 这个方法,让这个方法来调用打招呼。
public static void Greeting(string name,DeleGreeting greeting)
{
greeting.Invoke(name);
}
最后,我们来实例化这个委托,并调用这个方法。
static void Main(string[] args)
{
DeleGreeting method = new DeleGreeting(MyGreeting.GreetingChinese);
MyGreeting.Greeting("张三",method);
DeleGreeting method1 = new DeleGreeting(MyGreeting.GreetingEnglish);
MyGreeting.Greeting("lucy", method1);
Console.Read();
}
结果如下:
用这种方式实现的话,以后不管你添加多少种国家的打招呼。都不用去改动 Greeting(); 这个方法,只需要扩展一个打招呼的方法就行了。达到”对扩展开方,对修改封闭“的原则。
五、多播委托
接下来我们来看一下什么是多播委托
委托对象可使用 "+" 运算符进行合并。一个合并委托调用它所合并的两个委托。只有相同类型的委托可被合并。"-" 运算符可用于从合并的委托中移除组件委托。
也就是说,可以将多个方法绑定给同一个委托
DeleGreeting method = new DeleGreeting(MyGreeting.GreetingChinese);
method += new DeleGreeting(MyGreeting.GreetingEnglish);
MyGreeting.Greeting("李四", method);
结果: