Unsubscribe anonymous method in C#
Action myDelegate = delegate(){Console.WriteLine("I did it!");};
MyEvent += myDelegate;
// .... later
MyEvent -= myDelegate;
Just keep a reference to the delegate around.
Unsubscribing from anonymous delegate event
Anonymous delegates are not guaranteed to be unique as created by the compiler, when unsubscribing this lack of uniqueness of the same code will cause it to fail to unsubscribe the correct handler. The only way to do so safely is to keep a reference to the delegate and use that to unsubscribe, or change it to a full method.
Delegates are equal based on object instance and method signature I believe.
A possible duplicate:
How to remove a lambda event handler
Basically, keep a reference:
MouseEventHandler handler = (sender, e) =>
{
Dragging = true;
DragStart = new Point(e.X, e.Y);
control.Capture = true;
};
control.MouseDown += handler;
control.MouseDown -= handler;
Or turn the anonymous method into a proper method.
Adding and Removing Anonymous Event Handler
There's an MSDN page that talks about this:
How to Subscribe to and Unsubscribe from Events
Note in particular:
If you will not have to unsubscribe to [sic]
an event later, you can use the
addition assignment operator (+=) to
attach an anonymous method to the
event.
And also:
It is important to notice that you
cannot easily unsubscribe from an
event if you used an anonymous
function to subscribe to it. To
unsubscribe in this scenario, it is
necessary to go back to the code where
you subscribe to the event, store the
anonymous method in a delegate
variable, and then add the delegate to
the event . In general, we recommend
that you do not use anonymous
functions to subscribe to events if
you will have to unsubscribe from
the event at some later point in your
code.
Can an anonymous delegate unsubscribe itself from an event once it has been fired?
You can save an instance of the delegate before subscribing to the event:
public void QueueNotAvailable()
{
SomeHandler handler = null;
handler = (s,e) {
// ...
StateChanged -= handler;
};
StateChanged += handler;
}
I believe this should do it... I had to put the initial handler = null
in there otherwise you get 'Use of unassigned local variable' compilation errors, but I think it's actually benign.
How to unsubscribe an anonymous function in Dispose method of a class?
You can't, basically. Either move it into a method, or use a member variable to keep the delegate for later:
public class A : IDisposable
{
private readonly EventHandler handler;
public A()
{
handler = (sender, e) =>
{
Line 1
Line 2
Line 3
Line 4
};
B_Object.DataLoaded += handler;
}
public override void Dispose()
{
B_Object.DataLoaded -= handler;
}
}
Event unsubscription via anonymous delegate
You can extract the lamdba to a variable:
EventHandler func = (sender, e) =>
listView_PreviewTextInput(sender, e, listView);
if (((bool)e.NewValue))
{
listView.PreviewTextInput += func;
}
else
{
listView.PreviewTextInput -= func;
}
Unsubscribe events vis anonymous delegate
New answer, now the question has changed
You can't, basically. Your handler depends on dependencyObject
, which will be captured in a new object on each call, so you'll end up with unequal delegates.
You could create a new class which holds the dependency object and overrides Equals
to compare those objects instead of using anonymous functions, or you could just hold a reference to the previously-subscribed handler.
Old answer, when the delegate didn't depend on the parameters
The bizarre thing is that in this particular case, it looks like you're not capturing any local variables. So it's possible that if the only place you're subscribing to the event is from this method, you could get away with:
private static void Test(Object a, DependencyPropertyChangedEventArgs args)
{
NotifyCollectionChangedEventHandler handler =
(s, e) => SelectedItemsChanged(dependencyObject, e);
var oldObservable = args.OldValue as ObservableCollection<object>;
if (oldObservable != null)
{
oldObservable.CollectionChanged -= handler;
}
var newObservable = args.NewValue as ObservableCollection<object>;
if (newObservable != null)
{
newObservable.CollectionChanged += handler;
}
}
As you've only got one lambda expression now, I'd expect that to be converted into a single static method, so the freshly-created delegate will be equal to the original one.
However, I wouldn't recommend that. I'd just create the method yourself, and then use a method group conversion.
Do i have to unsubscribe from anonymous event handlers of local variables?
Your situation is fine; the event subscriber will not prevent the publisher from being collected, but the opposite can happen.
For example,
class Foo
{
public event EventHandler FooEvent;
void LeakMemory()
{
Bar bar = new Bar();
bar.AttachEvent(this);
}
}
class Bar
{
void AttachEvent(Foo foo)
{
foo.FooEvent += (sender, e) => { };
}
}
In this case, the instance of Bar
created within LeakMemory
can't be collected until either
- The anonymous method represented by the lambda is removed from
FooEvent
's invocation list - The instance of Foo to which it's attached can be collected
This is because the event (which is just some syntactic sugar over an ordinary delegate
instance) holds onto a list of delegates to invoke when it's invoked, and each of these delegates has, in turn, a reference to the object that it's attached to (in this case, the instance of Bar
).
Note that we're only talking about collection eligibility here. Just because it's eligible doesn't say anything about when (or even, really, if) it will be collected, just that it can be.
How do I Unregister 'anonymous' event handler
If you need to unregister an event, I recommend avoiding anonymous delegates for the event handler.
This is one case where assigning this to a local method is better - you can unsubscribe from the event cleanly.
Removing anonymous event handler
You can refer to your anonymous method from inside itself as long as you assign a delegate to a variable first:
EventHandler<SomeEventArgs> handler = null;
handler = (s, e) =>
{
_client.AddMemberToTeamCompleted -= handler;
callback(e.Result);
};
_client.AddMemberToTeamCompleted += handler;
Note that you need to declare the variable and assign it separately or the compiler will deem it uninitialized when you come to use it inside the method body.
Related Topics
How to Get the Current Username in .Net Using C#
Should I Avoid 'Async Void' Event Handlers
Awaiting Multiple Tasks With Different Results
Sharing Sessions Across Applications Using the ASP.NET Session State Service
How to Wait For a Thread to Finish With .Net
Correct Way to Load Assembly, Find Class and Call Run() Method
How to Load a .Net Assembly At Runtime and Instantiate a Type Knowing Only the Name
How to Achieve Base64 Url Safe Encoding in C#
Setting a Property by Reflection With a String Value
Sort a List from Another List Ids
How to Check For Internet Connectivity Using .Net
Creating Wizards For Windows Forms in C#
Why Would You Use String.Equals Over ==
How to Reflect Over the Members of Dynamic Object
Do You Need to Dispose of Objects and Set Them to Null
Still Confused About Covariance and Contravariance & In/Out