zoukankan      html  css  js  c++  java
  • .NET via C#笔记17——委托

    一、委托的内部实现

    C#中的委托是一种类型安全的回调函数,假设有这样一个委托:

    internal delegate void Feedback(int value);
    

    编译器会生成一个类:

    internal class Feedback : MultiCastDelegate {
        public Feedback(object @object, IntPtr method);
        // 用于同步回调
        public virtual void Invoke(int value);
        // 用于异步回调
        public virtual IAsyncResult BeginInvoke(int value, AsyncCallback callback, object @object);
        public virtual void EndInvoke(IAsyncResult result);
    }
    

    当创建一个委托时,编译器会把静态函数,成员函数等转化为这个类的实例对象。

    注意这里的修饰符是internal和deletage的修饰符是一致的。

    二、委托链

    MultiCastDelegate

    再来看下MultiCastDelegate这个基类,它有三个重要字段:

    字段 类型 说明
    _target object 如果引用一个实例方法,这里会存this
    _methodPtr IntPtr 标示回调的方法
    _invocationList object 用于表示委托数组
    这个类又继承自Delegate,这是C#的历史遗留问题,有些地方还需要用到Delegate作为参数类型。

    Delegate.Combine

    使用void Delegate.Combine(Delegate a, Delegate b)方法可以创建一个委托链。如果有一个参数为null返回值为非null的那个参数;如果都不是null,返回值为一个新的委托,其_invocaionList指向一个数组,数组的元素为这两个参数。

    a b 返回值
    null delegate1 delegate1
    delegate2 null delegate2
    delegate1 delegate2 delegateChain

    Delegate.Remove

    通过Remove方法可以删除委托(链)中从后向前找到的第一个符合条件的委托

    1. 如果没有了,返回null
    2. 如果只剩一个委托,返回这个委托。
    3. 如果还有多余一个委托,创建一个新的委托,和对应的数组,把剩下的委托拷贝进去。

    带返回值的委托

    如果委托类型带有返回值,对一个委托链进行Invoke操作会返回委托链中最后一个委托的调用结果。

    显式控制委托链的调用

    Delegate[] MultiCastDelegate.GetInvocationList()

    三、语法糖和lambda表达式

    1. 可以用+=-=表示Delegate.CombineDelegate.Remove方法。
    2. 隐式地使用静态函数或成员函数新建委托实例。
      void foo() {}
      void bar() {
          Action action = foo;
          action += foo;
          action -= foo;
      }
      

    lambda表达式

    int a = 0;
    int b = 1;
    Action action = ()=> { Console.WriteLine(a + b); };
    

    分两种情况:

    1. 没有引用局部变量,lambda表达式会转化为类中的一个私有方法。
      1. 如果没有引用类的成员函数或成员变量,这是一个静态方法。
      2. 否则会成为一个成员方法。
    2. 如果lambda表达式引用了局部变量,编译器会为lambda表达式创建一个局部类。
      1. 类的成员变量用来存储引用的局部变量。
      2. 类的成员函数表示这个lambda表达式。
  • 相关阅读:
    使用logstash配置nginx和tomcat日志统一收集到一台日志服务器
    文章
    辣和辛的区别是什么?
    prometheus和zabbix的对比
    从零搭建Prometheus监控报警系统
    Adobe Flash Professional 制作定制FLashPlayer播放器之读取配置文件(二)
    Adobe Flash Professional 制作定制FLashPlayer播放器(一)
    OSG+VS2015 测试Demo
    OSG+VS2015 入门教程---环境搭建
    button的类型?为什么button 会自动提交表单?
  • 原文地址:https://www.cnblogs.com/hamwj1991/p/12369195.html
Copyright © 2011-2022 走看看