委托内部

当声明一个委托,如下:

delegate void Feedback(int value);

编译器实际上定义了如下一个类:

    //所有创建的委托都继承自 MulticastDelegate 类
    //而 MulticastDelegate 类继承自 Delegate
    class Feedback : MulticastDelegate
    {
        //从 MulticastDelegate 类继承的 Delegate 类继承而来
        //当委托对象包装的是一个静态方法时,该字段存储的是null;包装的是实例方法时,存储的是回调方法要操作的对象的引用.
        object _target;

        //从 MulticastDelegate 类继承的 Delegate 类继承而来
        //一个内部的整数值,CLR用它表示要回调的方法
        //这个内部的整数值从 MethodDef 或者 MemberRef 元数据 token 获得
        IntPtr _methodPtr;

        //从 MulticastDelegate 类继承而来
        //该字段通常为null,当构造委托链时,它引用了一个委托数组
        object _invocationList;

        //构造方法
        public Feedback(object @object, IntPtr method)
        {
            this._target = @object;
            this._methodPtr = method;
        }

        //这个方法的参数,返回值和定义的委托的参数,返回值一模一样
        public virtual void Invoke(int value) { ...}

        //下面两个方法实现对回调方法的异步回调
        public virtual IAsyncResult BeginInvoke(int value,AsyncCallback callback,object @object) { ...}
        public virtual void EndInvoke(IAsyncResult result) { ...}
    }

    //Invoke方法的伪代码:
    public virtual void Invoke(int value)
    {
        Delegate[] delegateSet = _invocationList as Delegate[];
        if (delegateSet != null)
        {
            foreach (var d in delegateSet)
            {
                d(value);
            }
        }
        //==null 表示 不是委托链
        else
        {
            //这行代码接近实际的代码
            _methodPtr.Invoke(_target, value);
        }
    }

删除委托:

委托链不足的地方:

1.除了最后一个返回值,其他所有回调方法的返回值都会被丢弃;

2.如果被调用的委托中有一个抛出了异常或者阻塞了很长一段时间,那么后续的所有委托都调用不了.

原文地址:https://www.cnblogs.com/refuge/p/8953908.html