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.
精彩评论