跟小静学CLR via C#(12)-委托Delegate
本来按照进度应该学习事件了,可总觉得应该委托在前,事件在后,才好理解。
委托是一个类,它提供了回调函数机制,而且是类型安全的。使用委托可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,提高了程序的可扩展性。
使用委托
老规矩,先上个例子:
结果:
几点说明:
- 使用关键字delegate声明委托。委托是类型安全的,定义时其返回值类型、参数个数及参数类型要和想要调用的方法兼容。
- 在这个例子中,通过Introduce方法获取对delegateIntroduce委托对象的引用。委托对象相当于方法的包装器,使方法能通过包装器进行间接回调。
- 委托即允许调用静态方法(如①②),还允许调用实例方法(③)。
- 将一个方法绑定到委托时,允许引用类型的协变性和逆变性。(ps:陌生的词汇…)
- 协变性:方法能返回委托类型的派生类型;
- 逆变性:方法获取的参数可以是委托类型参数的基类。
注意:这两点只限于引用类型,不能用于值类型或者void。
编译结果
- 委托实际上会编译成一个类,包含四个方法:.ctor, Invoke, BeginInvoke, EndInvoke。
- 所有的委托都会自动继承类System.MulticastDelegate。 MulticastDelegate又继承自Delegate。
- MulticastDelegate类提供了三个公共字段:
名称
类型
说明
_target
System.Object
当委托调用静态方法时,该字段为null。当委托调用实例方法时,表示回调方法要操作的对象。
_methodPtr
System.InPtr
标识要回调的方法
_invocationList
System.Object
通常为Null,在委托链时可以引用一个委托数组
4. Delegate类提供了两个只读属性:
- Target :返回字段_target的值
- Method :将字段_methodPtr的值转换为MethodInfo并返回。
例如:
结果:
委托链
委托链是由委托对象构成的一个集合。这样就可以将多个方法绑定到同一个委托,调用这个委托的时候会依次调用其所绑定的方法。
接着上面的例子,我们修改Main方法的调用:
结果:
构造委托链时,用到了两个静态方法:
- Delegate.Combine(d1,d2) :将委托添加到委托链中。其间_invocationList字段会初始化为一个委托对象数组。上面例子构造完成后该_invocationList[0]被初始化为di1所引用的委托,以此类推。在执行时,发现_invocatonList字段不为空,则会遍历数组元素,顺序调用每个委托包装的方法。
- Delegate.Remove (d1,d2) :从d1的委托数组中字段中查找_target和_methodPtr字段与d2匹配的委托,找到后移除。即使匹配记录有多个,每次也只移除一个。
另外,MulticastDelegate类还提供了GetInvocationList()方法,来查看委托链中的委托数组。例如我们将调用委托的Introduce方法略作修改:
结果:
+=、-=
C#为委托的+=和-=操作符进行了重载,来简化语法。
执行结果相同。查看IL代码就会发现他们实际调用的是Combine和Remove方法。
THE END.
下次再碰上笔试或者面试的就不用紧张兮兮的了,可以洋洋洒洒的说一通了。
你也许喜欢:跟小静读CLR via C#(00)-开篇及目录
跟小静学CLR via C#(12)-委托Delegate相关推荐
- 跟小静读CLR via C#-开篇及目录
最近正在拜读Jeffrey大师的.NET巨作-<CLR via C#>.好书就像一杯茶,需要静下心来慢慢品.在写笔记的过程中,也加入了自己的思考:在和园友们的交流中,理解也不断的加深. 目 ...
- 跟小静读CLR via C#(02)-基元类型、引用类型、值类型
跟小静读CLR via C#(02)-基元类型.引用类型.值类型 一. 基元类型 编译器能够直接支持的数据类型叫做基元类型.例如int, string等.基元类型和.NET框架类库FCL存在着直接的映 ...
- 跟小静读CLR via C#(05)- 访问限定、数据成员
跟小静读CLR via C#(05)- 访问限定.数据成员 今天跟大家分享一下关于访问限定和数据成员的知识.主要包括以下两点: Abstract, sealed, virtual, new, over ...
- 跟小静读CLR via C#(06)- 构造器
跟小静读CLR via C#(06)- 构造器 最近忙着看新还珠,好几天不学习了.玩物丧志啊,罪过罪过. 今天总结的是类构造器的知识,其实这方面的文章蛮多的,可还是觉得亲自写一下对自己的思考和认识会有 ...
- 跟小静学MVC3[01]--创建第一个MVC3项目
[前言]从今天开始,小静要学习Pro ASP.NET MVC3 Framework这本经典大作了,我是下载的电子版学习的.在这里只是用作学习的记录,便于以后查阅,也为了督促自己坚持下去.不用于任何商业 ...
- 跟小静读CLR via C#(16)--泛型
泛型就像是一个模板,常常定义一些通用的算法,具体调用时再替换成实际的数据类型,提高了代码的可重用性. 一.初识泛型 1. 简单实例 以最常用的FCL中的泛型List<T >为例: stat ...
- 跟小静读CLR via C#(10)-参数
最近几天学了参数,其实对于参数本不陌生,从上学学C语言基础的时候就学过了.不过细心学下来,还是收获了一些. 一. 命名参数.可选参数 命名参数和可选参数是在Visual C#2010中引入的新特性. ...
- 跟小静读CLR via C#(18)——Enum
1. Enum定义 枚举类型是经常用的一种"名称/值"的形式,例如: public enum FeedbackStatus { New, ...
- 小余学调度:学习记录(2021年12月)
小余学调度系列文章,记录小余同学入职电力调度员一路的学习记录,由于工作性质,在这个系列,只写能公开的知识点,不涉及机密. 提示:专栏解锁后,可以查看该专栏所有文章 文章目录 一.对母线充电时,不能带电 ...
最新文章
- Rocksdb 的优秀代码(一) -- 工业级分桶算法实现分位数p50,p99,p9999
- 工业互联网的十大关键传感器
- thinkphp scws mysql_thinkphp buildHtml 函数实现网站静态化
- 5月19-20日WebRTCon 2018 梳理全球WebRTC技术实践与案例
- VC++ 非托管代码 托管代码
- Memcached原理与应用
- spring component-scan配置扫描多个包
- 如何在Scala中使用条件表达式
- linux ldap配置详解
- 【PRML 学习笔记】第一章 - 介绍 (Introduction)
- 深度linux清理空间,怎样清理内存缓存
- 飞鱼星路由器端口映射/端口转发的设置步骤及注意事项
- SiT9005:1 -141MHz单端扩频振荡器SSXO
- 2019年安徽大学ACM/ICPC实验室新生赛题解
- 搜索引擎相关站点收集
- Policy Evaluation收敛性、炼丹与数学家
- 提高访问国外网站速度
- js简繁转换,两种实现方式,妥妥的~
- 字符串匹配KMP算法及其时间复杂度分析
- 2.9寸墨水屏制作互联网时钟填坑手记
热门文章
- 基于CSDN完成TEASOFT的MOOC编辑整理
- 相机成像与校正原理:将外部世界进行降维
- Carmaer 500W 逆变器初步测试
- FZ35恒流电子负载检测测试
- 直播预告 | 全国大学生智能汽车竞赛全向行进组——基础培训
- python中pandas格式_Python学习笔记之数据分析中Pandas常用知识
- xml信息管理系统_WPF信息管理系统项目实战教程二:使用XAML实现页面布局
- oracle中DBWR全称,Oracle基本术语大全
- nginx配置静态资源html,通过nginx服务器访问静态资源(示例代码)
- sqlite3 增删更改查询 callback使用