I read this fantastic explanation from Eric Lippert concerning when an object, having a reference to another one via an event, is garbage-collected.
To prove what Eric said, I tried out this code:
using System;
public class Program
{
public static void Main()
{
{
var myClass = new GCClass();
LongLivingClass.MyEvent += myClass.HandleEvent;
} // LongLivingClass holds a reference to myClass
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
// expect: finalizer of GCLass not run
{
var myClass = new GCClass();
myClass.MyEvent += LongLivingClass.HandleEvent;
} // myClass can easily be GCed here
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
// expect: finalizer should run
Console.WriteLine("Finish");
}
}
class GCClass
{
public event EventHandler MyEvent;
public void HandleEvent(object o, EventArgs e) { }
~GCClass() { Console.WriteLine("Finalizer hit"); }
}
public class LongLivingClass
{
public static event EventHandler<EventArgs> MyEvent;
public static void HandleEvent(object o, EventArgs e) { }
}
As I expected the first GC.Collect
-block doesn't finalize anything, as the object simply is referenced by LongLvongClass
and thus survives a collection.
The second block however also does not call the finalizer, although myClass
is eligible for collection and we're even waiting for the finalizer to happen. However, my finalizer wasn't hit. As from GC.Collect() and Finalize I'd expect the finalizer to be hit here. I put a breakpoint into it, to show that.
Where did I go wrong here? I suppose myClass
is not collected in the second code-block, but I don't know why.