从程序的角度来讲:你就可以把委托看成是用来执行方法(函数)的一个“指针”
通俗的说就是:通过委托,我们可以把方法当成参数传递。
这里我举个例子:“设想,如果我们写了一个厨师做菜的方法,里面有拿菜、切菜、配菜、炒菜四个步骤,但编写此方法代码的人想让配菜这个环节让调用方法的人来实现,换句话说,就是想把方法作为参数来传递,那么怎么来实现呢?
方法1:使用接口,这里不是我们讨论的。
方法2:使用委托、微软为我们提供了一个叫做委托的类型,委托允许我们把一个方法当成参数传递。
委托的定义
就上面的例子,拿菜、切菜、配菜、炒菜我们定义4个方法,抽象成一个做菜类(ZuoCai.cs)。
public class ZuoCai
{
//定义一个做菜的委托
public delegate void ZuoCaiDelegate();
/// 拿菜方法
public void NaCai()
{
Console.WriteLine("A负责拿菜!");
}
/// 切菜方法
public void QieCai()
{
Console.WriteLine("B负责切菜!");
}
/// 配菜方法
public void PeiCai()
{
Console.WriteLine("C负责配菜!");
}
/// 炒菜方法
public void ChaoCai()
{
Console.WriteLine($"D负责炒菜!");
}
/// 开始做菜的方法
/// <param name="zuoCaiDelegate">委托作为参数传递</param>
public void StartZuoCai(ZuoCaiDelegate zuoCaiDelegate)
{
zuoCaiDelegate();
}
}
委托通过关键词delegate来定义,如下:
//定义一个做菜的委托
public delegate void ZuoCaiDelegate(int number);
当然在c#4.0后,微软为我们简化了委托的定义,帮我们定义了Action和Func两种委托类型,但是原理都是通过delegate来实现,这里不跑题,有兴趣的关注我的其他章节。
定义了委托后,如何使用委托呢,委托要使用,必须实例化,如下:
//实例化一个做菜类
ZuoCai zuoCai = new ZuoCai();
//实例化一个做菜的委托
ZuoCaiDelegate zuoCaiDelegate = new ZuoCaiDelegate(zuoCai.NaCai);
//把多个方法绑定到委托上。
zuoCaiDelegate += zuoCai.QieCai;
zuoCaiDelegate += zuoCai.PeiCai;
zuoCaiDelegate += zuoCai.ChaoCai;
委托可以绑定多个方法,支持+=(添加方法)和-=(取消方法),上面的定义就是将做菜的4个方法按顺序绑定在委托上,执行时候也是按顺序执行。
委托的使用
今天开店后,接了一个客户,然后店长安排做菜,如下。
public void Main()
{
//实例化一个做菜类
ZuoCai zuoCai = new ZuoCai();
//实例化一个做菜的委托
ZuoCaiDelegate zuoCaiDelegate = new ZuoCaiDelegate(zuoCai.NaCai);
zuoCaiDelegate += zuoCai.QieCai;
zuoCaiDelegate += zuoCai.PeiCai;
zuoCaiDelegate += zuoCai.ChaoCai;
//开始做菜
zuoCai.StartZuoCai(zuoCaiDelegate);
}
运行后结果如下:
忽然来了一个湖南的湘妹子客户,要求配菜时候多放点辣椒,怎么办呢?
方法1:店长要求改写ZuoCai类中的PeiCai方法。
如果又来了一个广东的客户,要求放点糖,难道又要改方法吗?如果很多各种各样需求的用户,都要靠改动原有的方法来实现,这个显然不合理的,违法了设计模式中的开闭原则。
方法2:店长要求在调用地方重新添加一个配菜方法(对扩展开放),这个是合理的建议,如下:
/// 配菜方法,加辣
void PeiCaiJiaLa()
{
Console.WriteLine("C负责配菜,要求多方点辣椒!");
}
只需要把调用方的
zuoCaiDelegate += zuoCai.PeiCai;
改为
zuoCaiDelegate += PeiCaiJiaLa;
完整代码如下:
//实例化一个做菜类
ZuoCai zuoCai = new ZuoCai();
//实例化一个做菜的委托
ZuoCaiDelegate zuoCaiDelegate = new ZuoCaiDelegate(zuoCai.NaCai);
zuoCaiDelegate += zuoCai.QieCai;
zuoCaiDelegate += PeiCaiJiaLa; //改为新定义的方法
zuoCaiDelegate += zuoCai.ChaoCai;
//开始做菜
zuoCai.StartZuoCai(zuoCaiDelegate);
运行结果如下:
上面的例子很清晰的演示了方法如何作为参数传递给另外一个方法,希望对大家有帮助。