首页 > 代码库 > 随手复习一下委托:delegate
随手复习一下委托:delegate
先骂个街,天儿太闷了……
随手复习一下委托,delegate 是一种函数指针,是 .net 提供的一种安全的函数指针,翻译的也很贴切,像是委托人,又像代理人,通过“委托”来执行一些函数而不是直接调用它。因为 C# 中委托被实现为指针链表,所以委托可以加入多个函数,一次性一块儿执行。
举个花生:小明(中国教育中最频繁出镜的绝对明星,不知为什么,我脑子里直觉般闪现第一个名字就是它,我Kao)要给他妈买酱油(貌似这个例子在多年前我自己的帖子里出现过),妈妈对小明的调用就表示为:
1 public class 妈妈2 {3 酱油 Get酱油()4 {5 var 孩子 = new 小明();6 retu 小明.打酱油();7 }8 }
当妈妈需要酱油时候,可以随时召唤小明去卖,那么如果需要盐呢、醋呢,假设 小明 都提供这样的方法,那么妈妈调用时候不得不这样:
1 public class 妈妈 2 { 3 调料 Get调料() 4 { 5 var 多种调料 = new 调料集合(); 6 var 孩子 = new 小明(); 7 调料集合.Add(小明.打酱油()); 8 调料集合.Add(小明.买醋()); 9 调料集合.Add(小明.买盐());10 11 return 多种调料;12 }13 }
事情到了现在,有两个很明显的问题:
1. 妈妈直接对小明进行了操作,这不是聪明的编码方式,因为如果妈妈还有闺女小红呢?让小红再去买东西就需要修改大量的妈妈类中的代码,显然很二。
2. 代码中规定了方法里只能调用小明三个技能,再多加两个或少买一个呢,就必须重新修改源代码了,所以不能做到动态的增减技能。
说到这里好像跑题去谈如何构建程序了,显然我还没到那个水平,回到委托,如果使用委托,至少可以同时解决这两个主要问题,因为:
1. 委托是“中间人”,妈妈可以全心关注对委托的控制,比如增加和减少要购买的东西
2. 委托是“相对抽象”的,妈妈通过委托既可以选择小明去买,也可以选择小红去买,一定程度上的解耦
用委托改一下,依旧忽略细节,只领会精神:
1 public class 妈妈 2 { 3 delegate 调料 买调料委托(); 4 private 买调料委托 妈妈让孩子去买调料; 5 } 6 7 public static class 小明 8 { 9 public static 调料 打酱油(){}10 public static 调料 买醋(){}11 public static 调料 买盐(){}12 }13 14 public static class 小红15 {16 public static 调料 打酱油(){}17 public static 调料 买米(){}18 public static 调料 买油(){}19 }
妈妈定义了一个“买调料”的委托,只要孩子有和这个委托签名一致的技能,妈妈就可以使用。有了这个基础,妈妈再考虑买调料时候就人性化的多,比如 1 日要买酱油、醋和米,就可以这样:
1 妈妈让孩子去买调料 = new 买调料委托(小明.打酱油);2 妈妈让孩子去买调料 += 小明.买醋();3 妈妈让孩子去买调料 += 小红.买米();4 妈妈让孩子去买调料();
妈妈把分属于两个孩子的三个技能添加到了委托,妈妈只需要运行这个委托,就可以运行一次买到三个东西,2 日妈妈不再需要买米而需要买盐时,就可以这样:
1 妈妈让孩子去买调料 -= 小红.买米();2 妈妈让孩子去买调料 += 小红.买盐();
从语法上来说我觉得已经比较人性化了,下面放上两个简单的示意代码,描述一下对委托的增减:
1 delegate void OnEventDelegate(string text); 2 OnEventDelegate OnEventHandler; 3 4 private void button1_Click(object sender, EventArgs e) 5 { 6 if (OnEventHandler == null) 7 { 8 OnEventHandler = new OnEventDelegate(ShowLabel1); 9 OnEventHandler += ShowLabel2;10 OnEventHandler += ShowLabel3;11 OnEventHandler += ShowLabel4;12 13 MessageBox.Show(string.Format("delegate object count: {0}", OnEventHandler.GetInvocationList().Count()));14 }15 }16 17 private void button2_Click(object sender, EventArgs e)18 {19 if (null != OnEventHandler)20 {21 foreach (var method in OnEventHandler.GetInvocationList())22 {23 MessageBox.Show(string.Format("delegate has method cout: {0}, now remove : {1}", OnEventHandler.GetInvocationList().Count(), method.Method.Name));24 25 OnEventHandler -= (OnEventDelegate)method;26 27 if (null == OnEventHandler)28 {29 MessageBox.Show("delegate remove all method");30 break;31 }32 }33 }34 }35 36 private void button3_Click(object sender, EventArgs e)37 {38 var timeString = DateTime.Now.Second.ToString();39 OnEventHandler(timeString);40 }
完整示例点击下载