1. 委托概述

这是一个新的概念,但是其本质并不是什么新鲜的事物,委托本质上就是一个类。只不过一般的类是数据的集合,委托保存的是一个或者多个方法。委托是引用类型,因此委托有引用和对象,同时委托对象中包含指向方法的引用,也就是C++中的函数指针的概念。也就是说委托中的数据成员都是一些函数指针,这些函数指针指向的方法和委托类型有相同的函数签名。

从上图中可以看出,委托和类基本上就是一个东西,过程都是一样的:

声明一个类型->声明该类型的引用变量(在栈中)->利用new在堆中创建实例对象,同时利用构造函数传参数,只不过委托实例利用默认的构造函数初始化调用列表->使用变量,通过引用变量,使用该类型的对象。

类对象的数据部分保存的是一般的数据类型 ,委托对象的数据部分保存的是函数指针,这些函数指针挨着盘的存放,构成了调用列表

2. 声明委托类型

委托是类型,就好像类是类型一样,所以委托类型必须在被用来创建引用变量以及类型的对象之前声明。

delegate void MyDel(int x);
//其中的MyDel就是委托类型名,类似于类名

注意:委托的类型声明,不需要在类内部声明,因为委托类型和类是同一个级别的。

3. 创建委托对象

委托是引用类型的,因此有引用和对象,就像上图中所示,引用变量存在栈内存中,委托对象存在堆内存中。

MyDel delVar;
//委托变量的声明,也就是委托引用

委托对象的创建:

delVar = new MyDel(myIntsObj.methodName);
dVar = new Mydel(SClass.staticMethodName);
//使用new关键字创建委托对象,同时给委托类型的默认构造函数传一个方法名作为参数。
//这个方法名就是委托对象调用列表中的第一个成员的方法的名字。

提示:在创建委托对象的时候有快捷的语句

delVar = myIntsObj.methodName;
dVar = SClass.staticMethodName;

  这是因为方法名称和其相对应的委托类型之间有隐式的转换。

图中的Invocation list里面存储的都是一些函数指针。

当然上面的创建对象可以在一条语句上完成:

MyDel delVar = new MyDel(myIntsObj.methodName);
MyDel dVar = new Mydel(SClass.staticMethodName);

或者:

MyDel delVar = myIntsObj.methodName;
MyDel dVar = SClass.staticMethodName;

4. 委托赋值

由于委托是引用类型的,可以通过给它赋值来改变包含在委托变量中的引用。旧的委托对象会被垃圾回收器回收。

MyDel delVar;

delVar = myIntsObj.methodName;
.
.
delVar = SClass.staticMethodName;

  

注意:这里用到了C#垃圾回收器的知识。

5. 修改委托

事实上,委托是恒定的,委托对象被创建后就不会再改变。任何对委托对象的修改都是创建一个新的委托,同时按照要求修改这个新委托对象的调用列表。

组合委托:

MyDel delA = myIntsObj.methodName;
MyDel delB = SClass.staticMethodName;
MyDel delC = delA + delB;//组合调用列表

委托增加和删除方法:

MyDel delVar = inst.MyM1;//创建并初始化
delVar += SCL.m3;//增加方法
delVar += X.Act;//增加方法

  

delVar -= SCL.m3;//从委托移除方法

  

6. 调用委托

试图调用空的委托对象会抛出异常,所以每次调用委托对象的时候,把委托对象和null进行比较,来判断委托对象的调用列表是否为空。

注意:

委托引用变量没有被初始化前,委托引用是null。委托对象中的调用列表为空,那么委托引用也为null。

调用方法是直接用委托引用,加上相对应的参数:

if(delVar != null)
{
delVar(55);
}

  

补充的知识点:

1. 当调用带返回值的委托对象时,调用列表中最后一个方法返回的值就是委托调用的返回值,调用列表中其他所有的方法的返回值都会被忽略。只是返回值被忽略,方法的操作还是有效果的(比如对全局变量的修改)。

2. 如果委托有引用参数,参数值会根据调用列表中的一个或多个方法的返回值而改变。在调用委托列表中的下一个方法时,参数的新值(不是初始值)会传给下一个方法。

[C#参考]委托机制的更多相关文章

  1. 【Unity3D技巧】在Unity中使用事件/委托机制(event/delegate)进行GameObject之间的通信 (二) : 引入中间层NotificationCenter

    作者:王选易,出处:http://www.cnblogs.com/neverdie/ 欢迎转载,也请保留这段声明.如果你喜欢这篇文章,请点[推荐].谢谢! 一对多的观察者模式机制有什么缺点? 想要查看 ...

  2. C++模拟C#事件委托机制(一)

    原文来自于http://www.cnblogs.com/netssfy/articles/1652671.html 写了一段时间的C#代码后确实发现C#的事件委托非常好用.于是便想是否在C++中也能如 ...

  3. Javascript事件模型系列(二)事件的捕获-冒泡机制及事件委托机制

    一.事件的捕获与冒泡 由W3C规定的DOM2标准中,一次事件的完整过程包括三步:捕获→执行目标元素的监听函数→冒泡,在捕获和冒泡阶段,会依次检查途径的每个节点,如果该节点注册了相应的监听函数,则执行监 ...

  4. Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论

    Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论 创建用户自定义的类加载器 要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的f ...

  5. Java虚拟机JVM学习05 类加载器的父委托机制

    Java虚拟机JVM学习05 类加载器的父委托机制 类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap ...

  6. Invoke() 方法是 Unity3D 的一种委托机制

    Invoke() 方法是 Unity3D 的一种委托机制 如: Invoke("SendMsg", 5);   它的意思是:5 秒之后调用 SendMsg() 方法: 使用 Inv ...

  7. java类加载器学习2——自定义类加载器和父类委托机制带来的问题

    一.自定义类加载器的一般步骤 Java的类加载器自从JDK1.2开始便引入了一条机制叫做父类委托机制.一个类需要被加载的时候,JVM先会调用他的父类加载器进行加载,父类调用父类的父类,一直到顶级类加载 ...

  8. Java基础---Java---基础加强---类加载器、委托机制、AOP、 动态代理技术、让动态生成的类成为目标类的代理、实现Spring可配置的AOP框架

    类加载器 Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader 类加载器也是Jav ...

  9. JavaScript 之默认行为 DOM2级,事件委托机制

    1. 事件默认行为及阻止方式    1.1 浏览器的默认行为       JavaScript事件本身所具有的属性,例如a标签的跳转,Submit按钮的提交,右键菜单,文本框的输入等.    1.2 ...

随机推荐

  1. MYSQL 执行计划

    Explain语法 EXPLAIN SELECT …… 变体: 1. EXPLAIN EXTENDED SELECT …… 将执行计划“反编译”成SELECT语句,运行SHOW WARNINGS 可得 ...

  2. [转]关于HTTP服务器每个客户端2个连接的限制

    这两天猫在家里搞一个多线程的断点续传得C#程序,发现同时只能开2个线程下载,其他的线程一律要等待,这样就导致下载大文件时其他线程经常超时,郁闷好久.今天回公司无意中发现了一个帖子,终于真相大白了, 现 ...

  3. [转]maven入门

    http://wentao365.iteye.com/blog/903396 Maven是一个采用纯Java编写的开 源项目管理工具.Maven采用了一种被称之为project object mode ...

  4. iOS设计模式——单例模式

    单例模式用于当一个类只能有一个实例的时候, 通常情况下这个“单例”代表的是某一个物理设备比如打印机,或是某种不可以有多个实例同时存在的虚拟资源或是系统属性比如一个程序的某个引擎或是数据.用单例模式加以 ...

  5. BootStrap 智能表单系列 八 表单配置json详解

    本章属于该系列的高级部分,将介绍表单中一些列的配置 1.config列的配置: 主要用于控制布局 :config:{autoLayout:true|'1,2,2,4'} true:根据配置项最里层的数 ...

  6. JS年月日三级联动下拉框日期选择代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. visual studio2013负载测试简单问题记录

    问题1: 错误 xxxx/xx/xx xx:xx:xx 未能对测试运行“xxxxxxxxxxx”进行排队: 活动的测试设置配置为使用 Visual Studio Online 运行测试. 使用团队资源 ...

  8. ssh环境搭建并实现登录功能

    参照了这篇博客,但是里面有些地方进行了更改 http://wenku.baidu.com/link?url=edeegTquV2eR3CJ5-zvNcJbyuq11Afp-lD2Fz2jfmuHhV1 ...

  9. 我们在 web 应用开发过程中经常遇到输出某种编码的字 符, 如 iso8859-1 等, 如何输出一个某种编码的字符串?

    public String translate (String str) { String tempStr = ""; try { tempStr = new String(str ...

  10. Jps介绍以及解决jps无法查看某个已经启动的java进程问题【盗用】

    1.jps的作用 jps类似linux的ps命令,不同的是ps是用来显示进程,而jps只显示java进程,准确的说是当前用户已启动的部分java进程信息,信息包括进程号和简短的进程command. 2 ...