正在阅读:讲故事谈.NET委托:一个C#睡前故事讲故事谈.NET委托:一个C#睡前故事

2006-03-08 14:08 出处: 作者:Chris Sells/著 袁晓辉/译 责任编辑:xietaoming

事件

  不幸的是,宇宙太忙了,也不习惯时刻关注它里面的个体,它可以用自己的委托替换了彼得老板的委托。这是把彼得的Worker类的的委托字段做成public的一个无意识的副作用。同样,如果彼得的老板不耐烦了,也可以决定自己来激发彼得的委托(真是一个粗鲁的老板):

// Peter's boss taking matters into his own hands
if( peter.completed != null ) peter.completed();

  彼得不想让这些事发生,他意识到需要给每个委托提供“注册”和“反注册”功能,这样监听者就可以自己添加和移除委托,但同时又不能清空整个列表也不能随意激发彼得的事件了。彼得并没有来自己实现这些功能,相反,他使用了event关键字让C#编译器为他构建这些方法:

class Worker {
...
    public event WorkStarted started;
    public event WorkProgressing progressing;
    public event WorkCompleted completed;
}

  彼得知道event关键字在委托的外边包装了一个property,仅让C#客户通过+= 和 -=操作符来添加和移除,强迫他的老板和宇宙正确地使用事件。

static void Main() {
    Worker peter = new Worker();
    Boss boss = new Boss();
    peter.completed += new WorkCompleted(boss.WorkCompleted);
    peter.started += new WorkStarted(Universe.WorkerStartedWork);
    peter.completed += new WorkCompleted(Universe.WorkerCompletedWork);
    peter.DoWork();

    Console.WriteLine(“Main: 工人工作完成”);
    Console.ReadLine();
}

“收获”所有结果

  到这时,彼得终于可以送一口气了,他成功地满足了所有监听者的需求,同时避免了与特定实现的紧耦合。但是他注意到他的老板和宇宙都为它的工作打了分,但是他仅仅接收了一个分数。面对多个监听者,他想要“收获”所有的结果,于是他深入到代理里面,轮询监听者列表,手工一个个调用:

public void DoWork() {
    ...
    Console.WriteLine("“工作: 工作完成”");
    if( completed != null ) {
        foreach( WorkCompleted wc in completed.GetInvocationList() ) {
            int grade = wc();
            Console.WriteLine(“工人的工作得分=” + grade);
        }
    }
}

键盘也能翻页,试试“← →”键

关注我们

最新资讯离线随时看 聊天吐槽赢奖品