|
| |
名片设计 CorelDRAW Illustrator AuotoCAD Painter 其他软件 Photoshop Fireworks Flash |
|
第十二章 委托 一、 委托的使用 静态委托和实例委托,使用方式类似,这里给出一个使用可变参数委托的例子: using System; public class DelCls { public delegate void DelDef(params string[] strParams); public static void CallDel(DelDef dd) { if(dd != null) //请务必在此处进行判定,这是个好习惯 { dd("Hello", "world"); } } } public class DelIns { //声明为private(私有)成员并不影响在类型内部使用委托 private static void ClsCallStr(params string[] strParams) //类型方式 { //将字符串数组并顺序输出 foreach(string str in strParams) { Console.Write("{0} ", str); } Console.WriteLine(); } public void InsCallStr(params string[] strParams) //实例方式 { //将字符串数组并反序输出 for(int i = strParams.Length - 1; i >= 0; i --) { Console.Write("{0} ", strParams[i]); } Console.WriteLine(); } public static void Main() { DelIns di = new DelIns(); DelCls.DelDef dd = null; Console.WriteLine("combine two delegate:"); dd += new DelCls.DelDef(DelIns.ClsCallStr); dd += new DelCls.DelDef(di.InsCallStr); DelCls.CallDel(dd); Console.WriteLine("remove the first delegate:"); dd -= new DelCls.DelDef(DelIns.ClsCallStr); DelCls.CallDel(dd); } } /*运行结果 combine two delegate: Hello world world Hello remove the first delegate: world Hello */ 在C#中使用委托方式: l 创建委托所使用的方式必须和委托声明相一致(参数列表、返回值都一致) l 利用 +=、-=来进行委托的链接或取消链接或直接使用Delegate.Combine和Delegate.Remove方式来实现 l 使用MulticastDelegate的实例方式GetInvocationList()来获取委托链中所有的委托 二、 委托揭秘 所有的委托都继续自MulticastDelegate,编译器在编译时刻为委托的声明生成了一个完整的委托类,重点注重其中的一些成员: ü 构造函数,传入委托的目标对象(实例)及指向回调方式的整数 ü 继续自MulticastDelegate的_target(System.Object)字段 ü 继续自MulticastDelegate的_methodPtr(System.Int32)字段 ü 继续自MulticastDelegate的_prev(System.MulticastDelegaet)字段 ü 生成的与方式声明相一致Invoke函数用以调用方式 可利用MulticastDelegate中的Method及Target属性来考察_methodPtr及_target字段的性质。 关于编译器生成的委托类及Invoke方式的调用情况,可通过使用ILDAsm.exe查看执行文件的IL代码获得 将上例中类型DelIns中的Main方式作如下修改,以实验GetInvocationList及MulticastDelegate中属性的使用: public class DelIns { … public static void Main() { … Delegate[] arrDel = dd.GetInvocationList(); foreach(DelCls.DelDef d in arrDel) { Console.WriteLine("Object type: {0}, Method name: {1}", (d.Target != null) ? d.Target.GetType().ToString() : "null", d.Method.Name); } … } … } /*运行结果 … Object type: null, Method name: ClsCallStr Object type: DelIns, Method name: InsCallStr … */ 三、 委托判等 首先判定_methodPtr及_target字段是否相等,若不等则返回false; 若相等,继承判定_prev是否为null(指向委托链头部的委托),若为null,则相等返回true; 若不等,继而判定委托链上所有委托对象,重复上述步骤。 可见牵涉到委托链的时候是个递归判定的过程。 四、 委托链 l 首先被加入到委托链中的委托位于委托链的尾部,但首先被调用,这是因为Invoke中利用递归对委托函数进行调用,这样位于头部的委托最后被调用。 l 委托调用后的返回值,只是最后一次被调用方式的返回值,即委托链头部委托的返回值 l 每调用一次Remove方式只删除匹配的第一个委托链 五、 委托与反射 以下是.net framework sdk文档提供的Delegate.CreateDelegate方式列表: 创建指定类型的委托以表示指定的静态方式。 [C#] public static Delegate CreateDelegate(Type, MethodInfo); 创建指定类型的委托,该委托表示要对指定的类实例调用的指定实例方式。 [C#] public static Delegate CreateDelegate(Type, object, string); 创建指定类型的委托,该委托表示指定类的指定静态方式。 [C#] public static Delegate CreateDelegate(Type, Type, string); 创建指定类型的委托,该委托表示要按指定的大小写敏感度对指定类实例调用的指定实例方式。 [C#] public static Delegate CreateDelegate(Type, object, string, bool); 下面的示例演示了创建静态方式委托、实例方式委托以及动态调用委托: using System; using System.Reflection; public class DelReflection { public delegate void GoGo(string strPam, Int32 nPam); public static void ClsGo(string strPam, Int32 nPam) { Console.WriteLine("In class, String:{0}, Int32:{1}", strPam, nPam); } public void InsGo(string strPam, Int32 nPam) { Console.WriteLine("In instance, String:{0}, Int32:{1}", strPam, nPam); } public static void Main() { Delegate d = null; d = Delegate.CreateDelegate(typeof(GoGo), typeof(DelReflection), "ClsGo"); if(d != null) d.DynamicInvoke(new Object[]{"Hello", 45}); DelReflection dr = new DelReflection(); d = Delegate.CreateDelegate(typeof(GoGo), dr, "InsGo"); if(d != null) d.DynamicInvoke(new Object[]{"Hello", 45}); } } /*运行结果 In class, String:Hello, Int32:45 In instance, String:Hello, Int32:45 */ 返回类别: 教程 上一教程: .NET之ASP Web Form迅速入门(5) 下一教程: 关于如何读取别人的网站使用NGWS NET classes 您可以阅读与"第十二章 委托[《.net框架程序设计》读书笔记]"相关的教程: · 第十四章 数组[《.net框架程序设计》读书笔记] · 第十三章 枚举类型与位标记[《.net框架程序设计》读书笔记] · 第十一章 事件[《.net框架程序设计》读书笔记] · 第十章 属性[《.net框架程序设计》读书笔记] · 第十五章 接口[《.net框架程序设计》读书笔记] |
| 快精灵印艺坊 版权所有 |
首页 |
||