WEB开发网
开发学院软件开发C语言 Effective C# 原则21:用委托来表示回调 阅读

Effective C# 原则21:用委托来表示回调

 2009-02-19 08:16:35 来源:WEB开发网   
核心提示:我:“儿子,到院子里除草去,Effective C# 原则21:用委托来表示回调,我要看会书,”斯科特:“爸,你可以支持多个用户目标,这样,我已经打扫过院子了,”斯科特:“爸

我:“儿子,到院子里除草去,我要看会书。”

斯科特:“爸,我已经打扫过院子了。”

斯科特:“爸,我已经把草放在除草机上了。”

斯科特:“爸,除草机不能启动了。”

我:“让我来启动它。”

斯科特:“爸,我做好了。”

这个简单的交互展示了回调。我给了我儿子一个任务,并且他可以报告状态来(重复的)打断我。而当我在等待他完成任务的每一个部份时,我不用阻塞我自己的进程。他可以在有重要(或者事件)状态报告时,可以定时的打断我,或者向我询求帮助。回调就是用于异步的提供服务器与客户之间的信息反馈。它们可能在多线程中,或者可能是简单的提供一个同步更新点。在C#里是用委托来表示回调的。

委托提供了一个类型安全的回调定义。尽管委托大多数是为事件使用的,但这不应该是C#语言中唯一使用这一功能的地方。任何时候,如果你想在两个类之间进行通信,而你又期望比使用接口有更少的偶合性,那么委托是你正确的选择。委托可以让你在运行确定(回调)目标并且通知用户。委托就是包含了某些方法的引用。这些方法可以是静态方法,也可以是实例方法。使用委托,你可以在运行时确定与一个或者多个客户对象进行交互。

多播委托包含了添加在这个委托上的所有单个函数调用。有两点要注意的:它不是异常安全的,并且返回值总是委托上最后一个函数调用后返回的值。

在多播委托调用的内部,每一个目标都会成功的调用。委托不会捕获任何的异常,也就是说,在委托链中抛出的任何异常都会终止委托链的继续调用。

在返回值上也存在一个简单的问题。你可以定义委托有返回值或者是void。你可能会写一个回调函数来检测用户的异常中断:

public delegate bool ContinueProcessing();
public void LengthyOperation( ContinueProcessing pred )
{
 foreach( ComplicatedClass cl in _container )
 {
  cl.DoLengthyOperation();
  // Check for user abort:
  if (false == pred())
   return;
 }
}

在单委托上这是工作的,但在多播委托上却是有问题的:

ContinueProcessing cp = new ContinueProcessing (
 CheckWithUser );
cp += new ContinueProcessing( CheckWithSystem );
c.LengthyOperation( cp );

从委托的调用上返回的值,其实是它的最后一个函数的调用上返回的值。其它所有的的返回值都被忽略。即,从CheckWithUser()返回的断言被忽略。

你可以自己手动的设置两个委托来调用两个函数。你所创建的每一个委托都包含有一个委托链。直接检测这个委托链,并自己调用每一个委托:

public delegate bool ContinueProcessing();
public void LengthyOperation( ContinueProcessing pred )
{
 bool bContinue = true;
 foreach( ComplicatedClass cl in _container )
 {
  cl.DoLengthyOperation();
  foreach( ContinueProcessing pr in
   pred.GetInvocationList( ))
   bContinue &= pr();
  if (false == bContinue)
   return;
 }
}

这时,我已经定义好了程序的语义,因此委托链上的每个委托必须返回真以后,才能继续调用。

委托为运行时回调提供了最好的方法,用户简单的实现用户对类的需求。你可以在运行时确定委托的目标。你可以支持多个用户目标,这样,用户的回调就可以用.Net里的委托实现了。

Tags:Effective 原则 委托

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接