看了《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. 避免Castle Windsor引起的内存泄露

    原文地址: http://nexussharp.wordpress.com/2012/04/21/castle-windsor-avoid-memory-leaks-by-learning-the-u ...

  2. 你写的Try...Catch真的有必要么?

    很多人喜欢用Try...Catch把每一个方法都包裹起来,可是真的有必要么? 为什么要这样做?我估计是大家被BUG吓怕了,生怕生产环境出现各种莫名其妙的错误,比如最经典的NullReferenceEx ...

  3. MySQL 变量和条件

    概述 变量在存储过程中会经常被使用,变量的使用方法是一个重要的知识点,特别是在定义条件这块比较重要. mysql版本:5.6 变量定义和赋值 #创建数据库 DROP DATABASE IF EXIST ...

  4. Docker+nginx+tomcat7配置简单的负载均衡

    本文为原创,原始地址为:http://www.cnblogs.com/fengzheng/p/4995513.html 本文介绍在Docker上配置简单的负载均衡,宿主机为Ubuntu 14.04.2 ...

  5. window系统JDK1.7的快速配置

    快速配置java环境变量 右键单击计算机--->属性 点击 "高级系统设置"--->"环境变量",出现环境变量设置窗口 系统变量--->新建 ...

  6. Android-简单的图片验证码

    Android-图片验证码生成1.为啥要验证码?图片验证码在网络中使用的是比较普遍的.一般都是用来防止恶意破解密码.刷票.论坛灌水.刷页等.2.怎样的验证码比较好?验证码的获取方式无非就两种,一种是后 ...

  7. Cookie与Session

    再说Cookie与Session之前,先要了解一下http协议. 何为http协议: http协议即超文本传输协议,一种基于浏览器请求与服务器响应的协议,该协议主要的特点就是它是一种无状态的协议(只针 ...

  8. Angular $watch

    如果想在某个属性发生变化的时候执行某些操作,那么scope.$watch是最佳选择 https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$w ...

  9. SQL Server ErrorLog

    SQL Server 使用ErrorLog记录SQL Server启动和运行过程中的信息,具体信息参考:<SQLSERVER errorlog讲解>.通常来说,ErrorLog是指SQL ...

  10. Enterprise Solution 虚拟测试环境

    在不联网的情况下,一台物理电脑安装数据库服务,VMware创建多个虚拟机,虚拟机中多个客户端并发连接到物理主机.可共用同一个物理主机的数据库,也可以测试多用户并发等问题. 1  安装微软虚拟网卡.在控 ...