代码改变世界

Effective C# 学习笔记(二十四)运用Delegates来实现回调

2011-07-15 19:33  小郝(Kaibo Hao)  阅读(366)  评论(0编辑  收藏  举报

代理提供了类型安全的回调定义,可以让你在运行时配置你的行为,并且可以通知多个客户端。代理其实是一个指向方法的引用,该方法可以是静态方法也可以是动态实例的。.NET Framework利用 Predicate<T>Action<T>Func<T>等类型来定义代理。

 

但由于历史原因,所有的代理都是多播代理。即所有的代理都是统一顺序执行的,而且若其中一个代理发生了异常,则剩下的代理将无法执行,而且返回值是最后一个添加到代理的方法的返回值。

 

举例说明:

//下面代码定义了某个集合中的任意一个类型的值不符合代理定义的条件后就会返回

public void LengthyOperation(Func<bool> pred)

{

foreach (ComplicatedClass cl in container)

{

cl.DoLengthyOperation();

// Check for user abort:

if (false == pred())

return;

}

}

单独执行上面的代码没有问题,但是在多播情况下就会产生歧义。

 

Func<bool> cp = () => CheckWithUser();

cp += () => CheckWithSystem();

c.LengthyOperation(cp);

 

上面的代码原意是校验CheckWithUser()CheckWithSystem()两个方法,但是只有CheckWithSystem会起作用,因为LengthOperation(cp)只会在意CheckWithSystem()返回值,因为其是最后一个被添加到代理中的方法。

 

所以对于代理的调用应如下做,通过遍历调用代理的方式实现:

public void LengthyOperation2(Func<bool> pred)

{

bool bContinue = true;

foreach (ComplicatedClass cl in container)

{

cl.DoLengthyOperation();

foreach (Func<bool> pr in pred.GetInvocationList())//遍历是所有代理

bContinue &= pr();//按位与操作确定返回值

if (!bContinue)

return;

}

}