从上面的类视图中我们看到,对委托的定义最终被编译成一个类,这个类中定义有4种方法:构造器,Invoke,BeginInvoke,EndInvoke。
所有的委托都继承自MulticastDelegate,而MulticastDelegate又继续至Delegate。这样我们定义的委托自然也就继承了MulticastDelegate的字段、属性和方法。在继承得到的所有成员中,有3个最重要的字段:
1、_target:指向调用回调函数时应该操作的对象。该字段用于实例方法的回调。
2、_methodPtr:一个内部的整数值,CLR用它来识别回调的方法。
3、_prev:指向另一个委托对象。
当编译器知道我们在构造的是一个委托时,它会分析源代码来确定要引用哪个对象和方法。其中对象引用会被传递给_target(对于静态方法,_target被置为null),一个特殊的标识方法的Int32值会被传递给_methodPtr,_prev在构造器中被置为null,它被用于在委托链中记录下一个委托的引用。
每个委托对象实际上是对方法及其调用操作的一个包装,MulticastDelegate中定义了两个只读属性,Target和Method,Target(其实就是前面的_target字段)属性返回一个方法回调时操作的对象的引用,Method属性返回一个标识回调方法的System.Reflection.MethodInfo对象。
委托链
前面介绍过MulticastDelegate中有一个_prev的私有字段,这个字段指向另一个MulticastDelegate对象的引用,这样就实现了委托链(其实与我们在学链表时的实现方式是一致的)。
当委托链表被调用时,它首先会调用委托中在其前面的委托对象,这里如果被调的回调方法具有返回值,将被丢失,委托链只会返回最后一次调用回调方法的返回值。
另外一个简单的委托和委托链的例子:
public delegate void WriteMessage();
public class WriteToWeb
... {
// 一个输出消息的静态方法
public static void StaticWrite()
...{
HttpContext.Current.Response.Write("委托调用了一个静态方法。<br />");
}
// 一个输出消息的类实例方法
public void Write()
...{
HttpContext.Current.Response.Write("委托调用了一个类实例方法。<br />");
}
}
... {
protected void Page_Load(object sender, EventArgs e)
...{
// 新建一个委托,回调函数是一个静态方法
WriteMessage wm = new WriteMessage(WriteToWeb.StaticWrite);
WriteToWeb w = new WriteToWeb();
// 新建一个委托并与加到先前建立的委托组成委托链,回调函数是一个类实例方法
wm += new WriteMessage(w.Write);
// 执行委托链上所有的回调函数
wm();
}
}