Sì, credo che la tua ipotesi sia corretta. Ho anche provato a scrivere un codice (brutto) per testare questa ipotesi:
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: Mantiene la scrittura:
Is 'class with event' alive: False; is 'class subscribing' alive: True
Se si mantiene vivo l'altro oggetto, non viene raccolto alcun oggetto, come sapevamo.
Entrambi gli oggetti vengono raccolti se escludiamo del tutto le righe keepAlive
.