开发者

Removing multicast delegate based on return value

I have a class that has a multicast delegate:

class Signaler
{
  public delegate bool SomeAction(string s);
  public SomeAction Actors {get; set;}

  void SignalActors()
  {
    Actors("blah blah");
  }
}

What I would like to do is to have an actor removed from Actors when that actor returns false as part of handling its action. What would be a good way to do this in the SignalActors() function?

Update: Possible solution based on John Skeet's solution:

class Signaler
{
  public delegate bool SomeAction(string s);
  public SomeAction Actors {get; set;}

  void SignalActors()
  {
    SomeAction canceledSubscri开发者_JAVA百科ptions=null;

    if (Actors!=null)
      foreach (SomeAction actor in Actors.GetInvocationList()) 
        if (!actor("Blah blah blah")) 
          canceledSubscriptions+=actor; 

    if (canceledSubscriptions!=null)
      foreach (SomeAction actor in canceledSubscriptions.GetInvocationList()) 
        Actors-=actor;
  }
} 


The simplest way is probably to actually build up a new delegate of all the ones that return true:

void SignalActors()
{
    SomeAction newActors = null;
    foreach (SomeAction actor in Actors.GetInvocationList())
    {
        if (actor("Blah blah blah"))
        {
            newActors += actor;
        }
    }
    Actors = newActors;
}

EDIT: The reason this is simpler than using -= is that it's obviously correct in terms of ordering. Whereas += always adds to the end of the invocation list, -= also takes away from the end of invocation list... so if you remove actors in the forward order, you can have a problem. Suppose we have the following actors:

A - returns false
B - returns true
C - returns true
A - (duplicate of the first) returns true this time

You should end up with {B, C, A} but if you subtract A from {A, B, C, A} you'll end up with {A, B, C}. My approach avoids this problem.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜