浅谈 C#委托
看了《CLR via C#》的17章委托后,为自己做一点浅显的总结,也分享给需要的人。
.NET通过委托来提供一种回调函数机制,.NET委托提供了很多功能,例如确保回调方法是类型安全的(CLR重要目标)。委托好允许顺序调用多个方法(委托链),并且支持调用静态方法和实例方法。
委托的基本语法就不多说了。
internal delegate void Feedback(int value);
public sealed class Program{
publick static void Main(){ } private static void DelegateDemo(){
Counter(1,2,new Feedback(WriteToConsole));
Program p=new Program p();
Counter(1,2,new Feedback(WriteToMsgBox)); } private static void Counter(int from, int to, Feedback fb){
for(int i=from;i<to;i++){
if(fb!=null)
fb(i);
} } private static void WriteToConsole(int val){
Console.WriteLine(val); } private void WriteToMsgBox(int val){
MessageBox.Show(val)
} }
和普通调用静态方法实例方法没区别,如果需要回调静态方法,那么className.FuncName(); 如果需要回调实例方法,那么Class_object.FuncName();
由于委托是类型安全的,它可以调用私用方法。
协变性和逆变性。
将一个方法绑定到委托的时候,C#和CLR都允许引用类型的协变性和逆变性,注意是引用类型哦。
delegate Object MyCallback(FileStream s); string SomeMethod(Stream s); //引用类型允许协变性,Stream是符合逆变性 int SomeOtherMethod(Stream s); //值类型不允许协变性
协变性是指方法能返回从委托的返回类型派生的一个类型,不能用于void。逆变性是指方法获取的参数是委托的参数类型的基类。
委托链
Delegate.Combine(FirstDelegateObj,SecondDelegateObj); FirstDelegateObj+=SecondDelegateObj; //语法糖效果,等同于上一行
上面代码就是在构造委托链。
委托链的原理大概就是:维护MulticastDelegate类中的三个重要的非公共字段中的_invocationList.这个字段维护了委托数组。
另外两个字段就是_target.当委托包装了一个静态方法时,这个字段为null.当委托对象包装了一个实例方法时,这个字段引用的是回调方法要操作的对象。
_methodPtr 一个内部的整数值,CLR用它标识要回调的方法。
在很多时候,执行委托链的过程中可能遭遇其中某个方法的阻塞和异常影响接下来的方法的执行。这个时候,我们的解决办法是使用MulticastDelegate为我们提供的GetInvocationList方法,获取由委托引用组成的数组,
每个委托引用只想链中的一个委托对象。我们可以通过遍历来执行每一个委托。
委托链执行后只会返回最后一个回调方法所返回的值、
下面给出MulticastDelegate中Invoke方法的伪代码实现,这个方法解释了委托的执行过程和原理。
public int Invoke(int value) { int result; Delegate[] delegateSet= _invoctionList as Delegate[]; if(delegateSet !=null) { //委托链 foreach(Feedback d in delegateSet) { result=d(value); } } else { //在执行对象上调用这个回调方法 result= _methodPtr.Invoke(_target,value); //以上代码接近实际代码,但实际上C#表示不出来。 } return result; }
浅谈 C#委托的更多相关文章
- 浅谈C#委托和事件
委托给了C#操作函数的灵活性,我们可使用委托像操作变量一样来操作函数,其实这个功能并不是C#的首创,早在C++时代就有函数指针这一说法,而在我看来委托就是C#的函数指针,首先先简要的介绍一下委托的基本 ...
- 浅谈C#委托和事件【转】
委托给了C#操作函数的灵活性,我们可使用委托像操作变量一样来操作函数,其实这个功能并不是C#的首创,早在C++时代就有函数指针这一说法,而在我看来委托就是C#的函数指针,首先先简要的介绍一下委托的基本 ...
- 浅谈C#委托和事件(转载)
委托给了C#操作函数的灵活性,我们可使用委托像操作变量一样来操作函数,其实这个功能并不是C#的首创,早在C++时代就有函数指针这一说法,而在我看来委托就是C#的函数指针,首先先简要的介绍一下委托的基本 ...
- 浅谈C#委托的用法-delegate[转]
一.委托的概念 委托和类一样是一种用户自定义类型,它存储的就是一系列具有相同签名和返回类型的方法的地址,调用委托的时候,它所包含的所有方法都会被执行. 借用百度上的一句话概括:委托是一个类,它定义了方 ...
- 浅谈C#委托的用法-delegate
2018年11月7日 小雨 一.委托的概念 委托和类一样是一种用户自定义类型,它存储的就是一系列具有相同签名和返回类型的方法的地址,调用委托的时候,它所包含的所有方法都会被执行. 借用百度上的 ...
- 【C#系列】浅谈委托和委托
本篇文章更适合具有一定开发经验,一定功底,且对底层代码有所研究的朋友!!! 本篇文章主要采用理论和代码实例相结合方法来论述委托和事件,涉及到一些边界技术,如软件架构的OCP原则(开-闭原则), 软件架 ...
- 浅谈线程池(中):独立线程池的作用及IO线程池
原文地址:http://blog.zhaojie.me/2009/07/thread-pool-2-dedicate-pool-and-io-pool.html 在上一篇文章中,我们简单讨论了线程池的 ...
- 浅谈线程池(上):线程池的作用及CLR线程池
原文地址:http://blog.zhaojie.me/2009/07/thread-pool-1-the-goal-and-the-clr-thread-pool.html 线程池是一个重要的概念. ...
- 谁还没遇上过NoClassDefFoundError咋地——浅谈字节码生成与热部署
谁还没遇上过NoClassDefFoundError咋地--浅谈字节码生成与热部署 前言 在Java程序员的世界里,NoClassDefFoundError是一类相当令人厌恶的错误,因为这类错误通常非 ...
随机推荐
- .NET Core 跨平台发布(dotnet publish)
.NET Core 跨平台发布(dotnet publish) ,无需安装.NET Core SDK,就可以运行. 前面讲解了.NET Core 的VSCode 开发.现在来讲讲发布(dotnet p ...
- 三种观察者模式的C#实现
系列主题:基于消息的软件架构模型演变 说起观察者模式,估计在园子里能搜出一堆来.所以写这篇博客的目的有两点: 观察者模式是写松耦合代码的必备模式,重要性不言而喻,抛开代码层面,许多组件都采用了Publ ...
- InstallShield2013 error 6109
InstallShield在没添加打包文件时是可以编译生成安装包的,在增加打包文件之后就报以下错误: ISEXP : error : -6109: Internal build error ISEXP ...
- java 成长之路
分享总结 title: java 成长之路 tags: grammar_cjkRuby: true 经验差异 1-3年 要求 建议 3-5年 建议 5年+ 经验差异 最近一年比较忙,经历了创业公司的倒 ...
- PHP的性能演进(从PHP5.0到PHP7.1的性能全评测)
本文是最初是来自国外的这篇:PHP Performance Evolution 2016, 感谢高可用架构公众号翻译成了中文版, 此处是转载的高可用架构翻译后的文章从PHP 5到PHP 7性能全评测( ...
- SVN代码冲突解决方案小集合
对于刚接触svn的人来说,svn冲突后,不能提交是件让人很郁闷的事情.最让人郁闷的事,是代码间的覆盖.你把我代码盖了,我会很火大的.谁把谁的盖了都不爽. 为什么会出现代码冲突问题呢,因为不同的人,同时 ...
- 我为NET狂-----大前端专帖
http://dnt.dkill.net/Article/Detail/321 本来前端的东西是不想开个专贴的,这样网友容易产生依赖,前端的东西看看书,平时仿照几个网站,遇到问题再调调增加点经验,基本 ...
- XenServer pool 移除server 设置master
如果因为Pool中Master主机由于某种原因导致失效,会引起整个Pool进入紧急模式,恢复步骤如下: 在成员服务器上输入如下命令 # xe host-emergency-ha-disable ...
- Autocomplete 自动补全(Webform实战篇)
开篇语 因为项目中需要用到一个自动补全的功能,功能描述: 需求一:新增收件人的时候,自动下拉显示出数据库中所有的收件人信息(显示的信息包括:姓名-收件地址-联系方式) 需求二:选中一个值得时候,分别赋 ...
- error: failed to push some refs to '......'解决方案
由于是初学者,又因为最近项目需要,只好边学边用吧. 在使用 “git push origin master” 时出现了以下问题 网上搜到的解决方案,可用: 先输入: git stash(用于暂存当前 ...