zoukankan      html  css  js  c++  java
  • C# Delegate略析

    C# Delegate略析

    C# Delegate,看起来和函数指针很类似,我简单理解为安全的方法套

    直接看代码来理解CLR之上的机制,废话不说

    对于一个简单的委托
    public delegate int BinaryOp(int x, int y);

    它将展开为
    sealed class BinaryOp : System.MulticastDelegate
    {
        public BinaryOp(object target, uint functionAddress);
        public void Invoke(int x, int y);
        public IAsyncResult BeginInvoke(int x, int y,
            AsyncCallback cb, object state);
        public int EndInvoke(IAsyncResult result);
    }

    注意到这是一个封闭的类,然后提供了异步调用的能力

    更泛的情况,一个类似代入公式的伪代码写法:
    public sealed class DelegateName : System.MulticastDelegate
    {
        public DelegateName (object target, uint functionAddress);
        public delegateReturnValue Invoke(allDelegateInputParams);
        public IAsyncResult BeginInvoke(allDelegateInputRefAndOutParams,
            AsyncCallback cb, object state);
        public delegateReturnValue EndInvoke(allDelegateRefAndOutParams,
            IAsyncResult result);
    }

    然后顺着继承树往上摸索,看看System.MulticastDelegate的部分成员
    [Serializable]
    public abstract class MulticastDelegate : Delegate
    {
        // Methods
        public sealed override Delegate[] GetInvocationList();

        // Overloaded operators
        public static bool operator ==(MulticastDelegate d1, MulticastDelegate d2);
        public static bool operator !=(MulticastDelegate d1, MulticastDelegate d2);

        // Fields
        private IntPtr _invocationCount;
        private object _invocationList;
    }

    这个可串行化标记很奇怪,MulticastDelegate 本身是一个虚类,不可能生成实例,这地方不大理解;根据.NET串行化的特点,该标记不可继承,所以说delegate本身是没有串行化能力的。其他的东西作用比较明显,GetInvocationList()为按调用顺序返回被调用方法列表,两个重载的运算符用来判断2个delegate是否相等(所谓相等,就是有相同的方法挂钩于上),两个私有字段和delegate的Multi-Invocation有关

    继续往上,看看Delegate的部分成员
    [Serializable, ClassInterface(ClassInterfaceType.AutoDual)]
    public abstract class Delegate : ICloneable, ISerializable
    {
        // Methods
        public static Delegate Combine(params Delegate[] delegates);
        public static Delegate Combine(Delegate a, Delegate b);
        public virtual Delegate[] GetInvocationList();
        public static Delegate Remove(Delegate source, Delegate value);
        public static Delegate RemoveAll(Delegate source, Delegate value);

        // Overloaded operators
        public static bool operator ==(Delegate d1, Delegate d2);
        public static bool operator !=( Delegate d1, Delegate d2);

        // Properties
        public MethodInfo Method { get; }
        public object Target { get; }
    }

    Combine()与Remove()、RemoveAll(),加上重载的"="、"+="、"-="、"+"、"-"运算符,我们的单个delegate变量可以操纵一个方法序列,并且我们可以根据自己的需要对这个方法序列进行修改。到这一步对delegate的能力可以了然了,突出表现为异步调用和可定制的多重调用(非认证的说法)。

    下面随手写个例子看看,来集中体现delegate的性质和用法

    class Program
    {
        public delegate int BinaryOp(int x, int y);

        public class SimpleMath
        {
            public static int Add(int x, int y)
            {
                int ans = x + y;
                Console.WriteLine("{0} + {1} = {2}", x, y, ans);
                return ans;
            }
            public static int Subtract(int x, int y)
            {
                int ans = x - y;
                Console.WriteLine("{0} - {1} = {2}", x, y, ans);
                return ans;
            }
        }

        static void Main(string[] args)
        {
            BinaryOp bOP = new BinaryOp(SimpleMath.Add);
            bOP += SimpleMath.Subtract;

            bOP(10, 5);
            Console.WriteLine();

            foreach (Delegate del in bOP.GetInvocationList())
            {
                Console.WriteLine(del.Method.ToString());
            }
            Console.WriteLine();

            BinaryOp bOPnew = new BinaryOp(SimpleMath.Subtract);
            bOPnew += SimpleMath.Add;

            foreach (Delegate del in bOPnew.GetInvocationList())
            {
                Console.WriteLine(del.Method.ToString());
            }
            Console.WriteLine();
            bOPnew(7, 3);
            Console.WriteLine();

            Console.WriteLine(bOP == bOPnew);
            bOP -= SimpleMath.Add;
            bOPnew -= SimpleMath.Add;
            Console.WriteLine(bOP == bOPnew);
        }
    }

    输出:
    10 + 5 = 15
    10 - 5 = 5

    Int32 Add(Int32, Int32)
    Int32 Subtract(Int32, Int32)

    Int32 Subtract(Int32, Int32)
    Int32 Add(Int32, Int32)

    7 - 3 = 4
    7 + 3 = 10

    False
    True

  • 相关阅读:
    博客园-随笔分类批量修改
    【读书笔记】--少有人走的路①:心智成熟的旅程
    自定义菜单用例
    自定义菜单创建接口
    发送消息---被动回复用户消息
    接收消息----接收语音识别结果
    接收消息----接收事件推送
    微信开发入门教程
    Hadoop维护IPC链接
    Hadoop建立IPC连接和数据读写
  • 原文地址:https://www.cnblogs.com/seven_cheng/p/1676116.html
Copyright © 2011-2022 走看看