深入理解委托(二)

=========
@ 委托链
=========
    MulticastDelegate 对象有一个私有字段 _prev,该字段指向另一个 MulticastDelegate对象的引用。这使得多个委托对象可以组合成为一个链表。
Delegate 类中定义了三个静态方法帮助我们来操作委托链表:
 

class System.Delegate{
 
// 组合 head 和 tail 所表示的链表,并返回 head。注意:head 将是最后一个被调用的委托对象。
 public static Delegate Combine(Delegate tail, Delegate head);

 
// 创建一个由委托数组表示的委托链表。注意:索引为 0 的元素将为链表头部,并将是最后一个被调用的对象。
 public static Delegate Combine(Delegate[] delegateArray);

 
// 从链表中移除一个和 value 的回调目标/回调方法相匹配的委托,新的链表头会被返回,并且将是最后一个被调用的委托对象。
 public static Delegate Remove(Delegate source, Delegate value);
}

    构造一个新的委托对象时,其 _prev 字段会被初始化为 null,这表示委托链表上没有其他对象,实际上它也一直为 null,不可改变,
当我们使用 Combine 方法时,_prev 字段会指向原先的委托链的头部,但此时创建了一个新的委托对象。
    下面通过代码演示:

Code

委托链调用描述(伪代码)

// 无返回值。
class D1 : MulticastDelegate{
    
public void virtual Invoke(){
        
// 如果该委托对象不是委托链表的 head,
        
// 那么调用前一个委托对象的 Invoke()。
        if(_prev != null){
            _prev.Invoke();
        }
        
// 调用自身的回调函数。
        _target.methodPtr();
    }


// 有返回值。
class D1 : MulticastDelegate{
    
public ReturnType virtual Invoke(){
        
// 如果该委托对象不是委托链表的 head,
        
// 那么调用前一个委托对象的 Invoke()。
        if(_prev != null){
            _prev.Invoke();
        }
        
// 调用自身的回调函数,前一个返回值将被丢弃。
        return _target.methodPtr();
    }
}

C#委托操作符
// C# 编译器会把 += 翻译为对 Delegate.Combine 方法的调用,
// -= 翻译为 Delegate.Remove 方法的调用。

Code

显示调用委托链表的委托对象
========================
@ 显示调用委托链表委托对象
========================

Code

输出:
 <-- f1
 <-- f2
 <-- [58225482] f3
 <-- [54267293] f3

 

posted @ 2008-06-29 03:13  NanKe Sir's Blog  阅读(524)  评论(0编辑  收藏  举报