Yes, I believe your assumption is correct. I also tried to write some (ugly) code to test this hypothesis:
class MyClassWithEvent
{
public event Action Fired;
void OnFired()
{
var d = Fired;
if (d != null)
d();
}
}
class MyClassSubscribing
{
void M()
{
}
public void DoSubscribe(MyClassWithEvent mcwe)
{
mcwe.Fired += M;
}
}
static class Test
{
static void Main()
{
WeakReference<MyClassWithEvent> wrMcwe;
WeakReference<MyClassSubscribing> wrMcs;
GetWeakRefs(out wrMcwe, out wrMcs);
// no garbage collect should occur just now, for we are not allocating new objects
// keep one of the objects alive; also try keeping the other one alive instead
MyClassSubscribing keepAlive;
wrMcs.TryGetTarget(out keepAlive);
//MyClassWithEvent keepAlive;
//wrMcwe.TryGetTarget(out keepAlive);
// loop not really needed
while (DateTime.Today.Year < 3000)
{
GC.Collect();
MyClassWithEvent x;
MyClassSubscribing y;
Console.WriteLine("Is 'class with event' alive: {0}; is 'class subscribing' alive: {1}", wrMcwe.TryGetTarget(out x), wrMcs.TryGetTarget(out y));
}
Console.WriteLine(keepAlive); // or just: GC.KeepAlive(keepAlive);
}
static void GetWeakRefs(out WeakReference<MyClassWithEvent> wrMcwe, out WeakReference<MyClassSubscribing> wrMcs)
{
var mcwe = new MyClassWithEvent();
wrMcwe = new WeakReference<MyClassWithEvent>(mcwe);
var mcs = new MyClassSubscribing();
wrMcs = new WeakReference<MyClassSubscribing>(mcs);
// link the two objects
mcs.DoSubscribe(mcwe);
// objects mcs and mcwe could be collected after this method exits
}
}
Output: Keeps writing:
Is 'class with event' alive: False; is 'class subscribing' alive: True
If you keep the other object alive, neither object is collected, as we knew.
Both objects are collected if we leave out the keepAlive
lines entirely.