Unsubscribe anonymous method in C#

81,067

Solution 1

Action myDelegate = delegate(){Console.WriteLine("I did it!");};

MyEvent += myDelegate;


// .... later

MyEvent -= myDelegate;

Just keep a reference to the delegate around.

Solution 2

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;

Solution 3

Since C# 7.0 local functions feature has been released, the approach suggested by J c becomes really neat.

void foo(object s, MyEventArgs ev)
{
    Console.WriteLine("I did it!");
    MyEvent -= foo;
};
MyEvent += foo;

So, honestly, you do not have an anonymous function as a variable here. But I suppose the motivation to use it in your case can be applied to local functions.

Solution 4

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.

Solution 5

In 3.0 can be shortened to:

MyHandler myDelegate = ()=>Console.WriteLine("I did it!");
MyEvent += myDelegate;
...
MyEvent -= myDelegate;
Share:
81,067

Related videos on Youtube

Eric
Author by

Eric

Clear, concise, effective, fun, flexible, articulate: I deliver results without supervision.

Updated on July 12, 2021

Comments

  • Eric
    Eric almost 3 years

    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?

  • BladeWise
    BladeWise almost 14 years
    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
    BladeWise almost 14 years
    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.
  • TDaver
    TDaver about 13 years
    That's exactly what I needed! I was missing the =null. (MyEventHandler foo = delegate {... MyEvent-=foo;}; MyEvent+=foo; didn't work...)
  • Jerry Nixon
    Jerry Nixon about 13 years
    If you think it's lame, don't post it.
  • Andres Scarpone
    Andres Scarpone about 12 years
    Resharper 6.1 doesn't complain if you declare it as an array. Seems a little weird, but I'm going to blindly trust my tools on this one: MyEventHandler[] foo = { null }; foo[0] = ... { ... MyEvent -= foo[0]; }; MyEvent += foo[0];
  • Eric Ouellet
    Eric Ouellet over 11 years
    I Jon, what do you meen ? I don't understand. does the solution exposed by "J c" will not work properly ?
  • Jon Skeet
    Jon Skeet over 11 years
    @EricOuellet: That answer is basically an implementation of "retain the delegate somewhere else so you can unsubscribe with exactly the same delegate you used to subscribe".
  • Eric Ouellet
    Eric Ouellet over 11 years
    Jon, I'm sorry, I read your answer many times trying to figure out what you mean and where the "J c" solution does not use the same delegate to subscribe and unsubscribe, but I can't fint it. Pehaps you can point me on an article that explain what you are saying ? I know about your reputation and I would really like to understand what you mean, anything you can link to would be really appreciate.
  • Eric Ouellet
    Eric Ouellet over 11 years
    I found : msdn.microsoft.com/en-us/library/ms366768.aspx but they do recommend not using anonymous but they do not say that there is any major problem ?
  • Eric Ouellet
    Eric Ouellet over 11 years
    I found it... Thanks a lot (see Michael Blome answer): social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread‌​/…
  • Jon Skeet
    Jon Skeet over 11 years
    @EricOuellet: The "J c" solution does use the same delegate. It puts it in a variable, and uses that variable for unsubscription. The "J c" solution also unsubscribes immediately that it's called, which is a little odd... but the bit of "store the delegate somewhere and use it in both places" is what I meant.
  • Eric Ouellet
    Eric Ouellet over 11 years
    If I understand what you are saying, I'm not agree. I think it is reasonable to unsubscribe from an event from the delegate itself. I had to do it in a TreeView see my comment in stackoverflow.com/questions/1905995/…. I don't see any problem of storing the delegate twice while one ref will be destroy (in GC) as soon as method end. Do you suggest better implementation than mine (in link) ? ... I really think there is applicable place where we need to have one time delegate and the way I did it (link) appears to me to be very ok.
  • Jon Skeet
    Jon Skeet over 11 years
    @EricOuellet: It's reasonable - it's just a little unusual, that's all - and not something that was asked in the question.
  • Eric Ouellet
    Eric Ouellet over 11 years
    Sorry, I just understand now what you meant. Thanks and sorry for my confusion. I misunderstood the answer/context.
  • dumbledad
    dumbledad about 10 years
    Does this mean I could accidentally unsubscribe a different instance (i.e. not me) from the event if they subscribed after me?
  • LuckyLikey
    LuckyLikey almost 8 years
    @dumbledad of course this would alaways deregister the last registered one. If you wanted to dynamically unsubscribe a specific anonymous delegate, you need to somehow identify it. I'd suggest keeping a reference then :)
  • LuckyLikey
    LuckyLikey almost 8 years
    what if MyEvent is invoked twice, before MyEvent -= myEventHandlerInstance; is ran? If it's possible, you'd have an error. But im not sure if that's the case.
  • LuckyLikey
    LuckyLikey almost 8 years
    Its pretty cool, what you are doing, but I can't imagine one case where this could be useful. But i't does really solve the OP's Question. --> +1. IMHO, one should simply not use anonymous delegates if they should be deregistered later. Keeping them is stupid --> better use Method. Removing just some delegate in Invocation list is pretty random and useless. Correct me if im wrong. :)
  • Mark Z.
    Mark Z. over 4 years
    To make the readability even better, you can move the MyEvent += foo; line to be before the declaration of foo.
  • Bill Tarbell
    Bill Tarbell over 2 years
    Even lame responses can have value to someone. In this case at least 6 people thought this approach was worthy of an upvote even though the author thought it lame.