Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EventHandlers and Anonymous Delegates / Lambda Expressions

I'm hoping to clear some things up with anonymous delegates and lambda expressions being used to create a method for event handlers in C#, for myself at least.

Suppose we have an event that adds either an anonymous delegate or a lambda expression (for you lucky crowds that can use newer versions of .NET).

SomeClass.SomeEvent += delegate(object o, EventArg e) { /* do something */ };

I have read that people in the past have forgotten about events that still have handlers which prevent the class from being garbage collected. How would one go about removing the added handler without just setting SomeEvent to null within the class. Wouldn't the following be an entirely new handler?

SomeClass.SomeEvent -= delegate(object o, EventArg e) { /* do something */ };

I could see storing the anonymous delegate or lambda expression in a variable. But that, to me at least, seems to defeat the entire purpose of being able to simply and succinctly add an event handler.

SomeEventDelegate handler = new SomeEventDelegate(delegate(object o, EventArg e) { /* do something */ });
SomeClass.SomeEvent += handler;
// ... stuff
SomeClass.SomeEvent -= handler;

Again, I understand that you could just do...

public override Dispose(bool disposing)
{
    _someEvent = null;
    this.Dispose();
}

But I'm more interesting with just removing the dynamically created method from the event. Hopefully someone can shed some light onto this for me. Thanks!

like image 308
Nicholas Mancuso Avatar asked Jan 13 '09 14:01

Nicholas Mancuso


2 Answers

If object X has an event handler whose target is object Y, then object X being alive means that object Y can't be garbage collected. It doesn't stop object X from being garbage collected.

Normally when something is disposed, it will become garbage pretty soon anyway, which means you don't have a problem.

The problem with events and GC is if you forget to remove a subscribed handler from a different object - i.e. you have a listener which is disposed, but will never be garbage collected because there's still a reference to it from the event in a different object.

like image 149
Jon Skeet Avatar answered Sep 17 '22 20:09

Jon Skeet


I think the problem is you seem to be proceeding from the assumption that having a delegate assigned to an object's event prevents it from being GCed.

This as a simple statement is not true.

With that said the perceived problem disappears.

Initially in garbage collection everything is garbage. The GC runs through every thing currently available globally and on each stack and from these those other objects that they are referencing and so on, marking each as not garbage.

How would such a graphing process manage to arrive at this object?

like image 20
AnthonyWJones Avatar answered Sep 19 '22 20:09

AnthonyWJones