views:

186

answers:

3

I started with a question, and in typing the question, found the answer, but instead of deleting, I thought it might be helpful to A) get confirmation, and B) help others.

If I have an event, and several places in the application add listeners, what is the best way to remove all listeners at once? For example, I can ...

myPage.OnPageOpened += OpenPage;

and later in my code ...

myPage.OnPageOpened -= OpenPage;

But what if I have unknown 3rd party subscribers and I want to press a magic Reset button that clears everything and starts from scratch?

You can use += and -= operators anywhere against the EventHandler, because the operator overloads are public. The = overloaded operator is private it can only be called in the defining class.

So in the defining class I can use this to clear my EventHandler.

OnPageOpened = null;

And to expose that functionality, I could ...

public void ClearPageOpenedEvents() {
   OnPageOpened = null;
}

Is that correct?

+1  A: 

That's the way to do it, but how does something outside the class know that the class should drop all its event listeners? What if someone extending/using your code is expecting that event on an ongoing basis?

JJO
It's during a reset, where the game is starting over. I agree that the public ClearPageOpenedEvents() is not a normal situation, and should be used with caution.
ScottCate
And should probably (at least in my case) be internal, instead of public.
ScottCate
Perhaps you could dispose of your objects and create new ones. That would also ensure that you are starting from a clean state. Cleaning up also has the advantage that you won't miss an event handler that needs to be cleared if you extend your class.
JJO
+1  A: 

Yes, you are correct. The reason for this is that the compiler creates a private delegate object under the covers, like this:

private EventHandler pageOpened;

public EventHandler PageOpened
{
    add { pageOpened += value; }
    remove { pageOpened -= value; }
}

Inside your class, you have a reference to the private delegate instance, so that's why you can do the assignment. You definitely want to expose a method to clear the targets if that's functionality you need; you don't want to expose the delegate itself.

Adam Robinson
A: 

You can use the assignment operator on an event because that's how adding and removing events work. Using Reflector shines a lot of light on how events are done in C#.

Given the simple class of

public class MyClass
{
  public event EventHandler MyEvent;
}

The following code is produced when compiled

public class MyClass
{
  private EventHandler MyEvent;

  public event EventHandler MyEvent;
}

So when you are referencing MyEvent you are referring to the private delegate variable MyEvent. The += and -= operators are "special" (because they aren't operators) and get changed into calling the add and remove methods that are created for the event (which use the assignment operator themselves).

[MethodImpl(MethodImplOptions.Synchronized)]
public void add_MyEvent(EventHandler value)
{
  this.MyEvent = (EventHandler) Delegate.Combine(this.MyEvent, value);
}

[MethodImpl(MethodImplOptions.Synchronized)]
public void remove_MyEvent(EventHandler value)
{
    this.MyEvent = (EventHandler) Delegate.Remove(this.MyEvent, value);
}
Samuel