先来到一个场景,小明、欧阳轰、王麻子是一个寝室的,有一天小明去吃午饭,欧阳轰说:帮我带一瓶饮料呗。这里,可以看出一个小小的委托关系,小明是欧阳轰的被委托人(经纪人),欧阳轰不用自己去做,请一个人代替他去做。这个时候王麻子也不想下楼了说:随便帮我带一个饭,还来一瓶饮料吧,我不挑食。这里的被委托人可以接受不同的委托人委托的事情,也可以是多件不同的事情。
下面我们用代码实现,这里呢用两种方式调用委托:
class Program
{
//定义委托
public delegate void DelegateBring(string name);
static void Main(string[] args)
{
Ming ming = new Ming();
//声明委托
DelegateBring delegateBring;
//实例化委托
delegateBring = new DelegateBring(ming.BringDrink);
//作为参数传入方法
DelegateReceive(delegateBring, "欧阳轰", "可乐");
delegateBring += new DelegateBring(ming.BringFood);
delegateBring("王麻子");
Console.Read();
}
public static void DelegateReceive(DelegateBring delegateBring, string stuName, string Drink)
{
//使用传入方法
delegateBring(stuName);
Console.WriteLine(" 备注:{0}", Drink);
}
}
class Ming
{
public void BringFood(string name)
{
Console.WriteLine("帮{0}带饭", name);
}
public void BringDrink(string name)
{
Console.WriteLine("帮{0}带一瓶饮料", name);
}
}
输出:
帮欧阳轰带一瓶饮料
备注:可乐
帮王麻子带一瓶饮料
帮王麻子带饭
这里,我们从刚刚的示例和代码中分析得出以下结论:
1.我们把相同的操作封装起来,重复使用,这很符合面向对象编程的思想,减少重复代码量
2.通过委托,我们把方法当作参数传入使用者,这里的小明做的事情可以看作相对的“接口”,这样的设计符合一个面向对象的原则:面对接口编程,不对实现编程
3.我们可以通过委托订阅很多个方法,不需要一个一个的去调用,那么实现这个重要功能的就是委托链(下面解释),这个也是委托的一个重要的特色
接下来我们了解委托的构造
通过断点我们可以看到我们实例化的delegate是继承System.MulticastDelegate,点开+号看到有个base,这个就是他的继承父类,也就是System.Delegate。
System.Delegate里面有两个很重要的方法:
1.Combine 添加指定的委托,也就是委托订阅常用在多播委托,可以用+=来完成
2.Remove这个方法跟combine方法相对,是取消某个多播委托上面的委托,通常让委托链上指定的委托为null回收内存,可以用-=来完成
System.MulticastDelegate里面的一个方法和两个属性,我们通过调试的监视窗口来观察他们
Method指向将要调用的方法的地址
Target这个存储的是指明调用方法所在的实例对象,如果委托调用的是一个静态方法,那么这个字段就是一个null,如果调用的是一个实例方法,那么它就是这个方法的对象
GetInvocationList()这个方法是获取多播委托的数组
接下来通过断点查看这两个类里面的构造
这里我们可以看到关键的几个属性方法
_target:对应的是Target属性
_methodPtr:对应的是Method属性,这里显示的是一串数字,可以理解是这个方法的一个回调指针
_invocationList:对应的是GetInvocationList()委托链
那么我们这里在最后面加入一段遍历这个委托链的代码,然后看看执行委托的顺序吧
for (int i = 0; i < delegateBring.GetInvocationList().Count(); i++)
{
Console.WriteLine(delegateBring.GetInvocationList()[i].Method.Name);
}
最后输出:
BringDrink
BringFood
那么查看了这么多信息,我们根据这些特性画一画这个委托链吧
总结:从委托的作用,委托的由来,再到一步步的编译和监控,再到后面的遍历委托链,大家应该对委托有了一个更深的了解。还是那句,习而简之。希望对大家有帮助
写在最后:这里没有用到反编译工具,也没有贴IL,我感觉这个玩意儿没多少人能看懂,也不算是汇编语言,所以就用这种断点,查看监视的方法简单文雅,准备了一个星期左右,写着写着感觉就成了一个灵魂画家。最后希望大家指出错误,给予我建议,爱你们,么么哒