Unsubscribe anonymous method in C#
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;
Related videos on Youtube
Eric
Clear, concise, effective, fun, flexible, articulate: I deliver results without supervision.
Updated on July 12, 2021Comments
-
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?
-
Marc Gravell over 9 yearsAs for why you can't do this: stackoverflow.com/a/25564492/23354
-
-
BladeWise almost 14 yearsUsing 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 almost 14 yearsI 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 about 13 yearsThat's exactly what I needed! I was missing the =null. (MyEventHandler foo = delegate {... MyEvent-=foo;}; MyEvent+=foo; didn't work...)
-
Jerry Nixon about 13 yearsIf you think it's lame, don't post it.
-
Andres Scarpone about 12 yearsResharper 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 over 11 yearsI Jon, what do you meen ? I don't understand. does the solution exposed by "J c" will not work properly ?
-
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 over 11 yearsJon, 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 over 11 yearsI 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 over 11 yearsI found it... Thanks a lot (see Michael Blome answer): social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/…
-
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 over 11 yearsIf 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 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 over 11 yearsSorry, I just understand now what you meant. Thanks and sorry for my confusion. I misunderstood the answer/context.
-
dumbledad about 10 yearsDoes this mean I could accidentally unsubscribe a different instance (i.e. not me) from the event if they subscribed after me?
-
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 almost 8 yearswhat 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 almost 8 yearsIts 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. over 4 yearsTo make the readability even better, you can move the MyEvent += foo; line to be before the declaration of foo.
-
Bill Tarbell over 2 yearsEven 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.