首页 >> C#.NET >> 正文
编程入门网-介绍.NET中的委派(Delegates)之三
来源:互联网 作者:赵湘宁 时间:2008-4-1

  因为所有的委派都派生于MulticastDelegate,它们继承了MulticastDelegate的域,属性和方法。在所有这些成员中,你要特别注意三个私有(private)域:

用于委派类型的私有域:

类型 描述
_target System.Object 指回调函数被调用时应该操作的对象。用于实例方法回调
_methodPtr System.Int32 内部整型,CLR用它来标示被回调的方法
_prev System.MulticastDelegate 指另一个委派对象,通常为null



   所有的委派都有代两个参数的构造器:一个参数是对象引用,一个是指代回调方法的整型。但是,如果你检查源代码,就会发现明白诸如App.FeedbackToConsole 或 appobj.FeedbackToFile的传递使用值进行的。你的敏感会告诉你这个代码不能编译!

   然而,编译器知道某个委派被创建,同时编译器解析源代码以决定引用哪个对象和方法。对象引用被传递为目标参数,并且用某个特定的Int32值(从某个MethodDef或MethodRef元数据符号获得)标示的方法被传递为methodPtr参数。对于静态方法,null被传递为目标参数。在构造器内部,这两个参数被存储在它们对应的私有(private)域中。

   另外,构造器将这个域置为null。这个域被用来创建一个MulticastDelegate对象链表。现在我们暂时忽略_prev域,在后续文章中将会详细讨论有关它的内容。

 每一个委派对象实际上就是一个方法包装器,当方法被调用时,受作用的对象被操作。MulticastDelegate类定义两个只读公共实例属性:Target和Method。给定一个委派对象引用,你就可以查询到它的这些属性。如果方法被回调,Target属性返回一个对将要操作的对象的引用。如果方法是静态的,则Target返回null。Method属性返回标示回调方法的System.Reflection.MethodInfo对象。

   你可以用几种方式使用这些信息。一种方式是检查是否某个委派对象引用特定类型的实例方法:

//

Boolean DelegateRefersToInstanceMethodOfType(

MulticastDelegate d, Type type) {


return((d.Target != null) && d.Target.GetType == type);

}

//


你还应该编写代码检查是否回调方法由专门的名字(如FeedbackToMsgBox):

//

Boolean DelegateRefersToMethodOfName(

MulticastDelegate d, String methodName) {


return(d.Method.Name == methodName);

}

//

  现在你知道了如何构造委派对象,下面让我们来谈谈回调方法是如何被调用的。为方便起见,我们还是使用

Set类中的ProcessItems:

//

public void ProcessItems(Feedback feedback) {

for (Int32 item = 1; item <= items.Length; item++) {

if (feedback != null) {

// 如果指定任何回调,则调用它们

feedback(items[item], item, items.Length);

}

}

}

//


   注释行下面的那一行代码就是调用回调方法。仔细看看代码,它调用feedback函数并传递三个参数。但是feedback是不存在的。再一次指出,编译器知道feedback是个引用某个委派对象的变量,并且编译器会产生实际的代码来调用委派对象的Invoke方法。换句话说,编译器看到下面这行代码后:

feedback(items[item], item, items.Length);

编译器产生的结果与下面这行源代码产生的结果一样:

feedback.Invoke(items[item], item, items.Length);
  事实上,通过使用ILDasm.exe程序检查ProcessItems代码结果(如图五),你能发现这一点。



图五 分解后的 Set类的 ProcessItems

   图五显示了用于Set类型中ProcessItems方法的微软中介语言。其中红色的箭头指向的指令调用Set.Feedback的Invoke方法。如果你修改源代码来显式调用Invoke方法,C#编译器报错,出错信息为:“error CS1533: Invoke cannot be called directly on a delegate”——意思是Invoke不能针对某个委派被直接调用。C#不允许你显式调用Invoke(但是,但别的编译器可以)。

   你会想起当编译器定义Feedback类的时候,它也定义了Invoke方法。当Invoke被调用时,它使用私有的_target和_methodPtr域来为特定对象调用希望的方法。注意Invoke方法的签名与委派的签名要完全匹配。也就是说,Feedback委派带三个参数并返回void,那么Invoke方法也必须带三个相同的参数并返回void。

结论

   本文讨论了有关委派的基本概念。根据本文目前所讨论的内容,现在你应该能够创建并使用它们。在后继文章中,我将解释链表中的委派链,以及一些有关MulticastDelegate的附加方法,System.Delegate类型和事件等......。等着我的好消息吧。

相关新闻
相关评论
 
评论表单加载中...
 
C#.NET文章

 在Visual C++应

 编辑:admin

 时间:2008-3-10


   编程入门网-介绍.NET中的委派(Delegates)之三
   编程入门网-介绍.NET中的委派(Delegates)之二
   编程入门网-介绍.NET中的委派(Delegates)之一
   编程入门网-用Visual C#实现文件下载功能
   编程入门网-用C#写简单的CGI程式
最新文章
   编程入门网-介绍.NET中的委派(Delegates)之三
   编程入门网-介绍.NET中的委派(Delegates)之二
   编程入门网-介绍.NET中的委派(Delegates)之一
   编程入门网-用Visual C#实现文件下载功能
   编程入门网-用C#写简单的CGI程式
总站搜索
搜索
 
热门文章
   oracle数据库文件中的导入\导出
   用Oracle10g列值掩码技术隐藏敏感数据
   VB程序中用ADO对象动态创建数据库和表-VB.NET
   用VB6写简单程序 让电骡自动关机-VB.NET
   使用.NET2.0编写COM组件供VB调用-VB.NET
   VB.NET:键盘控制焦点移动-VB.NET
   用VB.NET绘制GDI图形-VB.NET
   vb.net中应用 ArrayList 实例-VB.NET
 
推荐文章
ASP.NET中的状态管理-ASP.NET
VC、IE、ASP环境下打印、预备的完美解决方案
oracle数据库文件中的导入\导出
VB.NET中快速访问注册表技巧-VB.NET
在vb中实现超连接的方法!和直接发邮件-VB.NET
用VB做realplayer播放列表-VB.NET
在VB.NET中如何实现和利用SortedLists-VB.NET
利用VB.NET Stopwatch对象记录时间-VB.NET
成都古羌科技有限公司版权所有: Copyright@2007-2010 ,ALL Rights Reserved 蜀ICP备07017240号