Mi sembra che quando uso la classe WeakReference
su un metodo delegato di una classe oggetto, la classe dell'oggetto venga raccolta dal GC ma c'è ancora un'altra copia di essa che risiede nello ?GC non raccoglie quando WeakReference fa riferimento a un delegato?
Trovo difficile spiegare a parole. Darò un esempio. Ho la seguente classe di oggetti chiamati TestObject
:
class TestObject
{
public string message = "";
private delegate string deleg();
public TestObject(string msg)
{
message = msg;
}
public Delegate GetMethod()
{
deleg tmp = this.TestMethod;
return tmp;
}
public string TestMethod()
{
return message;
}
}
Ora, nella mia applicazione principale, tento di fare riferimento al metodo TestMethod
in TestObject
tramite un WeakReference
. L'intenzione è che il GC TestObject
possa essere raccolto da GC quando tutti i riferimenti rigidi sono andati. Ecco come il mio principale si presenta come:
static void Main(string[] args)
{
var list = new List<WeakReference>();
var obj = new TestObject("Hello 1");
list.Add(new WeakReference(obj.GetMethod()));
Console.WriteLine("Initial obj: " + ((Delegate)list[0].Target).DynamicInvoke()); //Works fine
obj = null; //Now, obj is set to null, the TestObject("Hello 1") can be collected by GC
GC.Collect(); //Force GC
Console.WriteLine("Is obj null: " + ((obj) == null ? "True" : "False"));
Console.WriteLine("After GC collection: " + ((Delegate)list[0].Target).DynamicInvoke());
Console.ReadKey();
}
Questa è l'uscita quando faccio funzionare il codice di cui sopra:
Ecco la cosa strana. Nella prima riga, obj
, è possibile stampare "Hello 1"
perché è stato appena inizializzato e obj
contiene un riferimento allo TestObject
. Tutto giusto. Successivamente, obj
è stato impostato su null
con obj = null
e GC è stato costretto a raccogliere. Quindi, nella seconda riga dell'output, obj
è true
da null. Infine, sull'ultima riga, dal momento che il GC ha ritirato lo obj
, mi aspetto che lanci uno NullReferenceException
o che non stampi nulla sull'output. Tuttavia, ha effettivamente stampato la stessa cosa della prima riga dell'output! Non dovrebbe già il TestObject
essere raccolto dal GC ?!
Questo pone la domanda se il TestObject
che è stato trattenuto per la prima volta in obj
sia stato successivamente raccolto dal GC o meno dopo aver impostato obj su null.
Se avessi passato l'intero oggetto in WeakReference
, ovvero new WeakReference(obj)
, invece di un delegato nello WeakReference
, avrebbe funzionato perfettamente.
Sfortunatamente, nel mio codice, ho bisogno di passare al delegato WeakReference
. Come posso fare in modo che WeakReference
funzioni correttamente in modo che il GC possa raccogliere l'oggetto semplicemente facendo riferimento a un delegato?