先骂个街,天儿太闷了……

随手复习一下委托,delegate 是一种函数指针,是 .net 提供的一种安全的函数指针,翻译的也很贴切,像是委托人,又像代理人,通过“委托”来执行一些函数而不是直接调用它。因为 C# 中委托被实现为指针链表,所以委托可以加入多个函数,一次性一块儿执行。

举个花生:小明(中国教育中最频繁出镜的绝对明星,不知为什么,我脑子里直觉般闪现第一个名字就是它,我Kao)要给他妈买酱油(貌似这个例子在多年前我自己的帖子里出现过),妈妈对小明的调用就表示为:

 public class 妈妈
{
酱油 Get酱油()
{
var 孩子 = new 小明();
retu 小明.打酱油();
}
}

小明打酱油

当妈妈需要酱油时候,可以随时召唤小明去卖,那么如果需要盐呢、醋呢,假设 小明 都提供这样的方法,那么妈妈调用时候不得不这样:

 public class 妈妈
{
调料 Get调料()
{
var 多种调料 = new 调料集合();
var 孩子 = new 小明();
调料集合.Add(小明.打酱油());
调料集合.Add(小明.买醋());
调料集合.Add(小明.买盐()); return 多种调料;
}
}

小明要买多种调料

事情到了现在,有两个很明显的问题:

1. 妈妈直接对小明进行了操作,这不是聪明的编码方式,因为如果妈妈还有闺女小红呢?让小红再去买东西就需要修改大量的妈妈类中的代码,显然很二。

2. 代码中规定了方法里只能调用小明三个技能,再多加两个或少买一个呢,就必须重新修改源代码了,所以不能做到动态的增减技能。

说到这里好像跑题去谈如何构建程序了,显然我还没到那个水平,回到委托,如果使用委托,至少可以同时解决这两个主要问题,因为:

1. 委托是“中间人”,妈妈可以全心关注对委托的控制,比如增加和减少要购买的东西

2. 委托是“相对抽象”的,妈妈通过委托既可以选择小明去买,也可以选择小红去买,一定程度上的解耦

用委托改一下,依旧忽略细节,只领会精神:

 public class 妈妈
{
delegate 调料 买调料委托();
private 买调料委托 妈妈让孩子去买调料;
} public static class 小明
{
public static 调料 打酱油(){}
public static 调料 买醋(){}
public static 调料 买盐(){}
} public static class 小红
{
public static 调料 打酱油(){}
public static 调料 买米(){}
public static 调料 买油(){}
}

妈妈用委托

妈妈定义了一个“买调料”的委托,只要孩子有和这个委托签名一致的技能,妈妈就可以使用。有了这个基础,妈妈再考虑买调料时候就人性化的多,比如 1 日要买酱油、醋和米,就可以这样:

 妈妈让孩子去买调料 = new 买调料委托(小明.打酱油);
妈妈让孩子去买调料 += 小明.买醋();
妈妈让孩子去买调料 += 小红.买米();
妈妈让孩子去买调料();

妈妈自由组合买东西

妈妈把分属于两个孩子的三个技能添加到了委托,妈妈只需要运行这个委托,就可以运行一次买到三个东西,2 日妈妈不再需要买米而需要买盐时,就可以这样:

 妈妈让孩子去买调料 -= 小红.买米();
妈妈让孩子去买调料 += 小红.买盐();

去掉米添上盐

从语法上来说我觉得已经比较人性化了,下面放上两个简单的示意代码,描述一下对委托的增减:

         delegate void OnEventDelegate(string text);
OnEventDelegate OnEventHandler; private void button1_Click(object sender, EventArgs e)
{
if (OnEventHandler == null)
{
OnEventHandler = new OnEventDelegate(ShowLabel1);
OnEventHandler += ShowLabel2;
OnEventHandler += ShowLabel3;
OnEventHandler += ShowLabel4; MessageBox.Show(string.Format("delegate object count: {0}", OnEventHandler.GetInvocationList().Count()));
}
} private void button2_Click(object sender, EventArgs e)
{
if (null != OnEventHandler)
{
foreach (var method in OnEventHandler.GetInvocationList())
{
MessageBox.Show(string.Format("delegate has method cout: {0}, now remove : {1}", OnEventHandler.GetInvocationList().Count(), method.Method.Name)); OnEventHandler -= (OnEventDelegate)method; if (null == OnEventHandler)
{
MessageBox.Show("delegate remove all method");
break;
}
}
}
} private void button3_Click(object sender, EventArgs e)
{
var timeString = DateTime.Now.Second.ToString();
OnEventHandler(timeString);
}

对委托的增减操作

完整示例点击下载

随手复习一下委托:delegate的更多相关文章

  1. [.NET] C# 知识回顾 - 委托 delegate (续)

    C# 知识回顾 - 委托 delegate (续) [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6046171.html 序 上篇<C# 知识回 ...

  2. [C#] C# 知识回顾 - 委托 delegate

    C# 知识回顾 - 委托 delegate [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6031892.html 目录 What's 委托 委托的属性 ...

  3. C# 委托Delegate(一) 基础介绍&用法

    本文是根据书本&网络 前人总结的. 1. 前言 定义&介绍: 委托Delegate是一个类,定义了方法的类型, 使得可以将方法当做另一个方法的参数来进行传递,这种将方法动态地赋给参数的 ...

  4. 为什么不能把委托(delegate)放在一个接口(interface)当中?

    stackoverflow上有人问,为什么不能把委托放在一个接口当中? 投票最多的第一个答案第一句话说,“A Delegate is just another type, so you don't g ...

  5. C# 代理/委托 Delegate

    本文转载自努力,努力,努力 1. 委托的定义:委托是函数的封装,它代表一"类"函数.他们都符合一定的签名:拥有相同的参数列表,返回值类型.同时,委托也可以看成是对函数的抽象,是函数 ...

  6. c# 委托 delegate

    委托是一种存储函数引用的类型,在事件和事件的处理时有重要的用途 通俗的说,委托是一个可以引用方法的类型,当创建一个委托,也就创建一个引用方法的变量,进而就可以调用那个方法,即委托可以调用它所指的方法. ...

  7. 理解委托(delegate)及为什么要使用委托

    理解委托(delegate)及为什么要使用委托 委托:是一种定义方法签名的类型. 当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联. 您可以通过委托实例调用方法. 上述为官方说法,理解起来 ...

  8. 深入理解委托(Delegate)

    前言 委托其实一直以来都感觉自己应该挺熟悉的,直到最近又去翻了翻 CLR via C#,感觉我之前的理解可能还有失偏颇.在这记录一下. 之前文章的链接: 接口和委托的泛型可变性 C#高级编程笔记 De ...

  9. C# -- 使用委托 delegate 执行异步操作

    C# -- 使用委托 delegate 执行异步操作 委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似. 与 C 中的函数指针不同,委托是面向对象的.类型安全的和保险的. 委托的 ...

随机推荐

  1. 什么时候rootViewController至tabbarController时刻,控制屏幕旋转法

    于ios6后,ios系统改变了屏幕旋转的方法,假设您想将屏幕旋转法,在需求rootvc里面制备,例如 UIViewController *viewCtrl = [[UIViewController a ...

  2. cocos2dx 3.1.1移植安卓apk (lua交叉编译器项目 mac环境)

    cocos2dx 3.1.1   lua项目安卓交叉编译 mac环境 本文基于ant,sdk,ndk,adt等软件和环境已经事前设置好 1\新建项目 在mac的终端下输入命令: cocos new t ...

  3. veridata实验举例(2)验证表BONUS与表SALGRADE两节点同步情况

    veridata实验举例(2)验证表BONUS与表SALGRADE两节点同步情况 续接前几篇文章: 1.GoldenGate配置(一)之单向复制配置 地址:点击打开链接 2.GoldenGate配置( ...

  4. file 上传文件后缀名 限制

    比如: 要求只能上传Excel <input type="file" accept="application/vnd.ms-excel,application/vn ...

  5. 用DIV+css写Table

    做出的效果样式如下图, 1,首先考虑的是如何显示border,就像是分割代码,我把border分割为最外层DIV全border,和内层DIV的right和bottom的border,就是右边和下边. ...

  6. java阅读器hdfs单纯demo

    周围环境:eclipse + eclipse hadoop插入. hadoop + rhel6.4 package test; import java.io.IOException; import j ...

  7. Yii Framework2.0开发教程(10)配合mysql数据库实现用户登录

    1.首先在mysql创建一个存用户的表格 create table test_user ( user_id bigint(20) unsigned not null auto_increment co ...

  8. Java笔试题集锦

    Java笔试题集锦 1.MVC的各个部分都有那些技术来实现?怎样实现? 答:MVC是Model-View-Controller的简写."Model" 代表的是应用的业务逻辑(通过J ...

  9. JVM相关知识(1)

    1.JVM内存管理的机制 内存空间划分为:Sun JDK在实现时遵照JVM规范,将内存空间划分为堆.JVM方法栈.方法区.本地方法栈.PC寄存器. 堆: 堆用于存储对象实例及数组值,可以认为Java中 ...

  10. ADS-B 雷达 显示终端5.8

    改动日志 1  更新背景地图. 增加了全国范围内的国际航路.区域航路信息,全部航路信息来自网络及中国民用航空局公布的公开资料:航路採用深蓝色画笔绘制航路中包括有航路代码.高度及报告点信息.代码及报告点 ...