看了《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#委托的更多相关文章

  1. 浅谈C#委托和事件

    委托给了C#操作函数的灵活性,我们可使用委托像操作变量一样来操作函数,其实这个功能并不是C#的首创,早在C++时代就有函数指针这一说法,而在我看来委托就是C#的函数指针,首先先简要的介绍一下委托的基本 ...

  2. 浅谈C#委托和事件【转】

    委托给了C#操作函数的灵活性,我们可使用委托像操作变量一样来操作函数,其实这个功能并不是C#的首创,早在C++时代就有函数指针这一说法,而在我看来委托就是C#的函数指针,首先先简要的介绍一下委托的基本 ...

  3. 浅谈C#委托和事件(转载)

    委托给了C#操作函数的灵活性,我们可使用委托像操作变量一样来操作函数,其实这个功能并不是C#的首创,早在C++时代就有函数指针这一说法,而在我看来委托就是C#的函数指针,首先先简要的介绍一下委托的基本 ...

  4. 浅谈C#委托的用法-delegate[转]

    一.委托的概念 委托和类一样是一种用户自定义类型,它存储的就是一系列具有相同签名和返回类型的方法的地址,调用委托的时候,它所包含的所有方法都会被执行. 借用百度上的一句话概括:委托是一个类,它定义了方 ...

  5. 浅谈C#委托的用法-delegate

    2018年11月7日     小雨 一.委托的概念 委托和类一样是一种用户自定义类型,它存储的就是一系列具有相同签名和返回类型的方法的地址,调用委托的时候,它所包含的所有方法都会被执行. 借用百度上的 ...

  6. 【C#系列】浅谈委托和委托

    本篇文章更适合具有一定开发经验,一定功底,且对底层代码有所研究的朋友!!! 本篇文章主要采用理论和代码实例相结合方法来论述委托和事件,涉及到一些边界技术,如软件架构的OCP原则(开-闭原则), 软件架 ...

  7. 浅谈线程池(中):独立线程池的作用及IO线程池

    原文地址:http://blog.zhaojie.me/2009/07/thread-pool-2-dedicate-pool-and-io-pool.html 在上一篇文章中,我们简单讨论了线程池的 ...

  8. 浅谈线程池(上):线程池的作用及CLR线程池

    原文地址:http://blog.zhaojie.me/2009/07/thread-pool-1-the-goal-and-the-clr-thread-pool.html 线程池是一个重要的概念. ...

  9. 谁还没遇上过NoClassDefFoundError咋地——浅谈字节码生成与热部署

    谁还没遇上过NoClassDefFoundError咋地--浅谈字节码生成与热部署 前言 在Java程序员的世界里,NoClassDefFoundError是一类相当令人厌恶的错误,因为这类错误通常非 ...

随机推荐

  1. Linux堆内存管理深入分析(下)

     Linux堆内存管理深入分析 (下半部) 作者@走位,阿里聚安全 0 前言回顾 在上一篇文章中(链接见文章底部),详细介绍了堆内存管理中涉及到的基本概念以及相互关系,同时也着重介绍了堆中chunk分 ...

  2. Linux RAID卡优化

    200 ? "200px" : this.width)!important;} --> 介绍 我们的生产服务器经常会做raid存储,但是单单做了raid就能保证性能高效和数据 ...

  3. [ASP.NET MVC 大牛之路]01 - 开篇

    匆匆2014,转眼就到末尾了.在这一年,你还有哪事情些想做而没有做? 2014年在我身上发生了两件意义重大的事,一是正月初一宝宝出生,我升级成为了爸爸:二是进入了一家创业公司,成为了技术负责人. 去年 ...

  4. Module Zero概览

    返回<Module Zero学习目录> 介绍 ABP框架的设计是独立于任何数据库模式的且尽可能地使用泛型.因此,它避开了一些要求数据存储的抽象和可选的概念(如审计日志,session管理和 ...

  5. 详解 JavaScript的 call() 和 apply()

    定义 ECMAScript规范为所有函数都包含两个方法(这两个方法非继承而来), call 和 apply .这两个函数都是在特定的作用域中调用函数,能改变函数的作用域,实际上是改变函数体内 this ...

  6. kettle资源库配置

    资源库的作用:资源库是用来保存操作步骤和相关的日志,转换,JOB 等信息.用户通过图形界面创建的的转换任务可以保存在资源库中.资源库可以是各种常见的数据库,用户通过用户名/ 密码来访问资源库中的资源, ...

  7. JSP的基本语法

    JSP的基本语法 一.JSP页面中的JAVA代码 二.JSP页面中的指令 三.JSP页面中的隐含对象(九大内置对象) 目录 一.JSP页面中的JAVA代码 JSP表达式(方便输出) JSP小脚本(完成 ...

  8. Liferay7 BPM门户开发之38: OSGi模块化Bndtools、Maven、Gradle开发构建入门

    前言 OSGi是目前动态模块系统的事实上的工业标准,它适用于任何需要模块化.面向服务.面向组件的应用程序.Eclipse如此庞大和复杂的插件体系,就是基于OSGi.Liferay也是基于OSGi.OS ...

  9. 深入浅出Hyper-V网络虚拟化技术

    年后综合症刚刚消失殆尽,转眼就要迎接各种新的工作任务了:之前写过一篇有关hyper-v网络虚拟化内容的博文,主要是从操作系统层面入手,概要性的总结了一下,基本也都是参考了大部分官方内容再加以个人修饰: ...

  10. Evaluate Math Expression

    Evaluate Math Expression eryar@163.com 摘要Abstract:本文简要介绍了数学表达式解析求值的几款开源软件,并结合程序代码说明了OpenCascade中表达式包 ...