一、概述
委托:本质就是一个类,与我们平常定义的类没什么多大区别。只是这个类的作用是描述一些方法,没有数据成员。一个委托定义了一类拥有同样返回类型和参数的方法规范。委托的声明语法就是一个没有方法体的方法前面加上delegate关键字。既然本质是一个类,那它就可以在任何定义普通类的位置来定义委托。委托是一个能把方法作为参数传递的对象。
事件是委托的一个实例。
二、委托知识点
1. 委托本质
通过ILSpy反编译后,我们可以看到委托类型是一个ckass,有.ctor(IL中的构造函数)Invoken方法和BeginInvoken、EndInvoken方法,Invoken是同步调用,而BeginInvoken、EndInvoken是异步调用。
2.委托的意义
**逻辑解耦,减少重复代码**
一句话解释:**一个方法委托了我,你调用我就等于调用了那个方法**
泛型委托:泛型委托Action<T>和Func<T>,前者代表无返回值,后者代表有返回值,
** 代码封装,支持扩展**
既然委托实例就是一个方法,结合泛型,那我们可以做到很多有趣的事情,例如给一个方法增加一个异常处理(这是一个无返回值的,当然也可以加一个有返回值的),
`public static void SafeInvoke(Action act)
{
try
{
Console.WriteLine("调用前...");
act.Invoke();
Console.WriteLine("调用后...");
}catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}`
如果你的方法指定给委托,那么就可以捕捉异常了,我们可以不需要再代码内处理异常,也不会破坏原类的封装,有点类似AOP(面向切片编程);
**匿名方法和Lambda表达式**
我们也可以直接给委托实例化时指定一个匿名方法,这样也可以减少代码的复杂度,还可以访问匿名方法外的变量,但是匿名方法内部不能使用break,contine等跳转语句
`Func<Animal,bool> func=delegate(Animal animal)
{
return animal.IsHungry>0;
}`
Lambda表达式代替匿名方法,Lambda运算符“=>”(发音Goesto)的左边列出了需要的参数,右边时利用参数方法的实现代码。
`Func<Animal,bool> func=animal=>return animal.IsHungry>0;`
异步多线程
异步多线程的实现都是基于委托的,委托有BeginInvoken和EndInvoken,我们可以发现BeginInvoken实际上是启用一个线程来调用方法的。
三.事件
事件几乎是无处不在的,它提供一种发布/订阅机制。我们做桌面开发的event关键字的委托实例。事件只能用+=来注册方法,只能在方法外部声明在内部调用,普通委托实例多用于回调,而事件多用于外部接口
四.总结
委托就是描述一类方法的类型,委托的实例就是代表一个方法。事件是委托的实例,最终是用来完成某一业务逻辑的一部分,只是这部分会变化,那么就将变化的形成封装出去,交给上层来指定,通过事件可以提供一个供外部扩展动作的接口
这世间万物都遵循着一个规则,任何事物都需要由简入繁,再由繁入简。最终达到道归一的境界。