views:

3102

answers:

6

Is it possible to unsubscribe an anonymous method from an event?

If I subscribe to an event like this:

void MyMethod()
{
    Console.WriteLine("I did it!");
}

MyEvent += MyMethod;

I can un-subscribe like this:

MyEvent -= MyMethod;

But if I subscribe using an anonymous method:

MyEvent += delegate(){Console.WriteLine("I did it!");};

is it possible to unsubscribe this anonymous method? If so, how?

+5  A: 

From memory, the specification explicitly doesn't guarantee the behaviour either way when it comes to equivalence of delegates created with anonymous methods.

If you need to unsubscribe, you should either use a "normal" method or retain the delegate somewhere else so you can unsubscribe with exactly the same delegate you used to subscribe.

Jon Skeet
A: 

Kind of lame approach:

public class SomeClass
{
  private readonly IList<Action> _eventList = new List<Action>();

  ...

  public event Action OnDoSomething
  {
    add {
      _eventList.Add(value);
    }
    remove {
      _eventList.Remove(value);
    }
  }
}
  1. Override the event add/remove methods.
  2. Keep a list of those event handlers.
  3. When needed, clear them all and re-add the others.

This may not work or be the most efficient method, but should get the job done.

casademora
+24  A: 
var myDelegate = delegate(){Console.WriteLine("I did it!");};

MyEvent += myDelegate;


// .... later

MyEvent -= myDelegate;

Just keep a reference to the delegate around.

Jacob
removed my previous comment. I see now... the brackets `delegate()` are optional.
Peter Perháč
+11  A: 

One technique is to declare a variable to hold the anonymous method which would then be available inside the anonymous method itself. This worked for me because the desired behavior was to unsubscribe after the event was handled.

Example:

MyEventHandler foo = null;
foo = delegate(object s, MyEventArgs ev)
    {
        Console.WriteLine("I did it!");
        MyEvent -= foo;
    };
MyEvent += foo;
J c
Using this kind of code, Resharper complains about accessing a modified closure... is this approach reliable? I mean, are we sure that the 'foo' variable inside the body of the anonymous method, really references the anonymous method itself?
BladeWise
I found an answer to my dubt, and it is that 'foo' will truly hold a reference to the anonymous method itslef. The captured variable is modified, since it is captured before the anonymous method get assigned to it.
BladeWise
+4  A: 

In 3.0 can be shortened to:

MyHandler myDelegate = ()=>Console.WriteLine("I did it!");
MyEvent += myDelegate;
...
MyEvent -= myDelegate;
+1  A: 

If you want to be able to control unsubscription then you need to go the route indicated in your accepted answer. However, if you are just concerned about clearing up references when your subscribing class goes out of scope, then there is another (slightly convoluted) solution which involves using weak references. I've just posted a question and answer on this topic.

Benjol