学习《深切了然C#》—— 委托的三结合、合併与删除和小结 (第二章1.1—1.4)

声明了一个SayHelloWorld的委托类型,①声明委托,开放-封闭原则,可以选择将委托看作之定义了一个方法的接口,开放-封闭原则,可以选择将委托看作之定义了一个方法的接口

寄托计算

  1. 寄托封装了包蕴特殊重回值和一组参数作为,类似于单一办法接口。
  2. 信托项目注解中描述的品类签字决定了章程哪个方法可用于委托实例,同不经常候也调整了调用具名。
  3. 开创委托实例,须要二个艺术以及调用方法的靶子。
  4. 信托实例是不易变的。
  5. 每一种委托实例都富含贰个调用列表——一个操作列表。
  6. 信托实例可以统一到一块,也足以从二个寄托实例中删除另一个。

那篇就写到这里。下篇大家将持续学习《深刻通晓C#》的相干知识。谢谢!

        [System.Security.SecuritySafeCritical]  
        protected override sealed Delegate CombineImpl(Delegate follow)
        { 
            if ((Object)follow == null) 
                return this;
            if (!InternalEqualTypes(this, follow))
                throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTypeMis"));

            MulticastDelegate dFollow = (MulticastDelegate)follow;
            Object[] resultList; 
            int followCount = 1; 
            Object[] followList = dFollow._invocationList as Object[];
            if (followList != null) 
                followCount = (int)dFollow._invocationCount;

            int resultCount;
            Object[] invocationList = _invocationList as Object[]; 
            if (invocationList == null)
            { 
                resultCount = 1 + followCount; 
                resultList = new Object[resultCount];
                resultList[0] = this; 
                if (followList == null)
                {
                    resultList[1] = dFollow;
                } 
                else
                { 
                    for (int i = 0; i < followCount; i++) 
                        resultList[1 + i] = followList[i];
                } 
                return NewMulticastDelegate(resultList, resultCount);
            }
            else
            { 
                int invocationCount = (int)_invocationCount;
                resultCount = invocationCount + followCount; 
                resultList = null; 
                if (resultCount <= invocationList.Length)
                { 
                    resultList = invocationList;
                    if (followList == null)
                    {
                        if (!TrySetSlot(resultList, invocationCount, dFollow)) 
                            resultList = null;
                    } 
                    else 
                    {
                        for (int i = 0; i < followCount; i++) 
                        {
                            if (!TrySetSlot(resultList, invocationCount + i, followList[i]))
                            {
                                resultList = null; 
                                break;
                            } 
                        } 
                    }
                } 
                if (resultList == null)
                {
                    int allocCount = invocationList.Length; 
                    while (allocCount < resultCount)
                        allocCount *= 2; 

                    resultList = new Object[allocCount];

                    for (int i = 0; i < invocationCount; i++)
                        resultList[i] = invocationList[i];

                    if (followList == null) 
                    {
                        resultList[invocationCount] = dFollow; 
                    } 
                    else
                    { 
                        for (int i = 0; i < followCount; i++)
                            resultList[invocationCount + i] = followList[i];
                    }
                } 
                return NewMulticastDelegate(resultList, resultCount, true);
            } 
        } 
 [System.Runtime.InteropServices.ComVisible(true)] 
        public static Delegate Combine(params Delegate[] delegates) 
        {
            if (delegates == null || delegates.Length == 0) 
                return null;

            Delegate d = delegates[0];
            for (int i = 1; i < delegates.Length; i++) 
                d = Combine(d,delegates[i]);

            return d; 
        }

public static Delegate Combine(Delegate a, Delegate b) 
        {
            if ((Object)a == null) 
                return b;

            return  a.CombineImpl(b);
        } 

目录

  • 一言以蔽之委托的重组

  • 集结和删除委托

  • 信托总括

    接下去大概的领悟一下下边所建议的4项原则:

 [System.Security.SecuritySafeCritical] 
        protected override MethodInfo GetMethodImpl()
        { 
            if (_invocationCount != (IntPtr)0 && _invocationList != null) 
            {
                Object[] invocationList = _invocationList as Object[];
                if (invocationList != null)
                {
                    int index = (int)_invocationCount - 1; 
                    return ((Delegate)invocationList[index]).Method;
                } 
                MulticastDelegate innerDelegate = _invocationList as MulticastDelegate; 
                if (innerDelegate != null)
                { 
                    return innerDelegate.GetMethodImpl();
                }
            } 
            else if (IsUnmanagedFunctionPtr())
            { 
                if ((_methodBase == null) || !(_methodBase is MethodInfo)) 
                {
                    IRuntimeMethodInfo method = FindMethodHandle();
                    RuntimeType declaringType = RuntimeMethodHandle.GetDeclaringType(method);
                    if (RuntimeTypeHandle.IsGenericTypeDefinition(declaringType) || RuntimeTypeHandle.HasInstantiation(declaringType)) 
                    { 
                        RuntimeType reflectedType = GetType() as RuntimeType; 
                        declaringType = reflectedType;
                    }
                    _methodBase = (MethodInfo)RuntimeType.GetMethodBase(declaringType, method);
                } 
                return (MethodInfo)_methodBase;
            } 
            return base.GetMethodImpl(); 
        }

轻松易行委托的重组

委托四部曲:

  1. 声称委托项目。
  2. 总得有二个办法饱含了要实行的点子。
  3. 必得成立一个信托实例。
  4. 总得调用委托实例

①宣称委托

 public delegate void SayHelloWorld(string message);  //① 声明委托类型

如上,评释了二个SayHelloWorld的嘱托项目,由System.MulticastDelegate派生,而System.MulticastDelegate又派生自
System.Delegate
。与该类型相配的办法的签名一个都不能够少使用叁个string类型作为参数和重临一个void类型。

②要实行的措施

public static void Say(string message) //② 必须有一个方法包含了要执行的代码;        {            Console.WriteLine;        }

方法能够是静态方法恐怕三个实例方法。

③ 必得成立三个委托实例

SayHelloWorld saymessage = new SayHelloWorld;  //③ 必须创建一个委托实例

④ 调用委托实例

 saymessage.Invoke("HelloWorld"); //④ 必须调用委托实例

也可以saymessage(“HelloWorld”);

全部代码:

 1 public static class Program 2     { 3         public delegate void SayHelloWorld(string message);  //① 声明委托类型 4         static void Main(string[] args) 5         { 6             SayHelloWorld saymessage = new SayHelloWorld;  //③ 必须创建一个委托实例 7             saymessage += SayName;   //增加委托实例 8             saymessage.Invoke("HelloWorld"); //④ 必须调用委托实例 9             saymessage -= Say; //删除委托实例10             Console.WriteLine("这是一种调用方法:");11 12             //返回委托的调用列表13             System.Delegate[] delegates = saymessage.GetInvocationList();14             //注意这里的delegates列表中存储的是SayHelloWorld类型的委托15             Console.WriteLine("这是二种调用方法:");17             foreach (SayHelloWorld say in delegates)18             {19                 saymessage("HelloWorld");20             }       22             Console.ReadKey();23         }24         public static void Say(string message) //② 必须有一个方法包含了要执行的代码;25         {26             Console.WriteLine;27         }28         public static void SayName(string name)29         {30             Console.WriteLine;31         }32 33     }

 
 再来具体看一下Remove()方法的平底实现代码,RemoveAll和Remove八个章程为System.Delegate类型中,CombineImpl方法在MulticastDelegate重写。:

   
谈及到C#的宗旨性格,“委托”是不得不去领悟和深深深入分析的四个天性。对于许多刚入门的程序猿聊到“委托”时,都会想到“将艺术作为艺术的参数进行传递”,比较多时候都只是精晓轻便的概念,重假设因为“委托”在明亮上有较其余特色相比难的地点。在本次表达中,不会将委托的简要注明和调用作为根本。

群集和删除委托

寄托实例不仅仅三个操作,但真实意况要多少复杂一点,委托实例实际有七个操作列表与之提到。称之为委托实例列表。而小编辈一般用+=和-=操作符来对信托实例的加码和删除。调用委托实例时,它的持有操作都按梯次实施。倘使委托的签订协议具备一个非
void 的回到类型,则 Invoke 的再次回到值是最后三个操作的重返值。相当少有非 void
的信托实例在它的调用列表中钦命八个操作,因为那象征任何全数操作的再次回到值永久都看不见。除非每一回调用代码应用Delegate.GetInvocationList
获取操作列表时,都显式调用有些委托。借使调用列表中的任何操作抛出七个特别,都会堵住实行后续的操作。

   
 委托类型实际上只是参数类型的一个列表以及重回类型。规定了品种的实例能代表的操作。在调用二个信托实例的时候,必需有限帮忙使用的参数完全同盟,何况能以钦点的艺术选拔再次回到值。对于信托实例的创设,取决于操作使用实例方法照旧静态方法(借使操作是静态方法,钦赐项目名称就可以,假若是操作实例方法,须求先创建项目标实例)。对于信托的调用,能够直接调用委托的实例的办法就足以做到对应的操作。

   
在“委托”的有关定义中,我们能够简单看出,“委托与艺术“相相比较于“接口与类”有着设计意见上的相似部分,产生的背景源于”设计规范“中的”开放-密闭原则“,”开放-密封“原则:是说软件实体(类,模块,函数等等)应该能够扩张,可是不可修改。换一种说法或然越来越好的精通”对于扩充是开放的,对于改造是查封的“,面前境遇新的急需,对于程序的更换是由此扩充新的代码举行的,实际不是改造现成的代码。

     2.不可能不有三个主意包罗了要实施的代码。

      [System.Security.SecuritySafeCritical] 
        public override sealed Delegate[] GetInvocationList()
        {
            Delegate[] del;
            Object[] invocationList = _invocationList as Object[];
            if (invocationList == null)
            { 
                del = new Delegate[1];
                del[0] = this; 
            } 
            else
            { 
                int invocationCount = (int)_invocationCount;
                del = new Delegate[invocationCount]; 

                for (int i = 0; i < invocationCount; i++) 
                    del[i] = (Delegate)invocationList[i]; 
            }
            return del; 
        }

   
“委托”没有要求一直定义一个要推行的一坐一起,而是将那么些行为用某种格局“满含”在八个目标中。那么些目的能够像别的任何对象这样采取。在该指标中,能够实行封装的操作。能够选择将委托看作之定义了贰个措施的接口,将委托的实例看作完毕了足够接口的指标。

 
 以上是对信托的连锁定义,以及有关委托的局地操作方法的表明,未有实际提议什么去创设和行使委托,因为委托的简短创建和一般选用,对于大多数开拓者来说是周旋较为轻便的,因为微软在持续的对C#的语法实行提高和改造,比非常的大的简化了相应的操作。但是幸而由于在应用层做了很大的卷入,那也会形成天性在底层的复杂度逐步的附加。

 
 在C#中委托用delegate关键字定义,使用new操作符构造委托实例,选拔古板的点子调用语法来回调函数(只是要用引用了信托对象的二个变量取代方法名)。在C#中,委托在编写翻译的时候会被编写翻译成类。对于信托的叁个验证:委托是叁个类,它定义了主意的花色,使得能够将艺术当作另两个格局的参数来拓展传递。委托类既可嵌套在二个品类中定义,也能够在大局范围钦赐义。由于委托是类,凡是能够定义类的地方,都足以定义委托。

     3.必需创设贰个信托实例。

   
在“委托”的相关定义中,大家得以轻易看出,“委托与办法“相对比于“接口与类”有着设计观念上的一般部分,产生的背景源于”设计条件“中的”开放-密封原则“,”开放-密封“原则:是说软件实体(类,模块,函数等等)应该能够增加,不过不得修改。换一种说法只怕越来越好的了然”对于扩张是开放的,对于改动是密闭的“,面前碰到新的供给,对于程序的改变是因而扩张新的代码实行的,并非退换现成的代码。

   具体来看一下Combine()方法的最底层完结代码:

   具体来看一下Combine()方法的最底层实今世码:

 
 在地点提到了寄托列表中出现非void实例调用,如若委托实例中冒出四个非void调用,况兼要求得到具有的信托实例的重返值结果,那么相应怎样操作,在.NET红提供了一个措施GetInvocationList(),用于获取委托链表。

 
 以上是对信托的有关定义,以及关于委托的一些操作方法的认证,未有切实可行提出什么去创设和使用委托,因为委托的粗略创设和一般接纳,对于抢先八分之四开拓者来讲是相对较为轻易的,因为微软在反复的对C#的语法进行进级换代和修改,相当大的简化了相应的操作。不过幸亏出于在应用层做了相当大的包装,那也会促成脾气在尾部的复杂度逐步的增大。

   
以上五个章程为System.Delegate类型中,CombineImpl方法在MulticastDelegate重写。

 
在以上的代码中,大家掌握到了在.NET底层是怎么着促成委托实例的绑定和删除绑定。

 public static Delegate RemoveAll(Delegate source, Delegate value) 
        {
            Delegate newDelegate = null; 

            do
            {
                newDelegate = source; 
                source = Remove(source, value);
            } 
            while (newDelegate != source); 

            return newDelegate; 
        }

[System.Security.SecuritySafeCritical] 
        public static Delegate Remove(Delegate source, Delegate value)
        {
            if (source == null) 
                return null;

            if (value == null) 
                return source;

            if (!InternalEqualTypes(source, value))
                throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTypeMis"));

            return source.RemoveImpl(value); 
        }

        [System.Security.SecuritySafeCritical] 
        protected override sealed Delegate RemoveImpl(Delegate value)
        {             MulticastDelegate v = value as MulticastDelegate; 

            if (v == null) 
                return this; 
            if (v._invocationList as Object[] == null)
            { 
                Object[] invocationList = _invocationList as Object[];
                if (invocationList == null)
                {
                    if (this.Equals(value))
                        return null; 
                } 
                else
                { 
                    int invocationCount = (int)_invocationCount;
                    for (int i = invocationCount; --i >= 0; )
                    {
                        if (value.Equals(invocationList[i])) 
                        {
                            if (invocationCount == 2) 
                            { 
                                return (Delegate)invocationList[1-i]; 
                            }
                            else
                            {
                                Object[] list = DeleteFromInvocationList(invocationList, invocationCount, i, 1); 
                                return NewMulticastDelegate(list, invocationCount-1, true);
                            } 
                        } 
                    }
                } 
            }
            else
            {
                Object[] invocationList = _invocationList as Object[]; 
                if (invocationList != null) {
                    int invocationCount = (int)_invocationCount; 
                    int vInvocationCount = (int)v._invocationCount; 
                    for (int i = invocationCount - vInvocationCount; i >= 0; i--)
                    { 
                        if (EqualInvocationLists(invocationList, v._invocationList as Object[], i, vInvocationCount))
                        {
                            if (invocationCount - vInvocationCount == 0)
                            { 
                                return null; 
                            } 
                            else if (invocationCount - vInvocationCount == 1)
                            { 
                                return (Delegate)invocationList[i != 0 ? 0 : invocationCount-1];
                            }
                            else 
                            {
                                Object[] list = DeleteFromInvocationList(invocationList, invocationCount, i, vInvocationCount); 
                                return NewMulticastDelegate(list, invocationCount - vInvocationCount, true); 
                            }
                        } 
                    }
                }
            }

            return this;
        }