Wydaje mi się, że gdy używam klasy WeakReference
dla metody delegatów klasy obiektu, klasa obiektu jest zbierana przez GC, ale jest jeszcze inna jej kopia znajdująca się w WeakReference
?GC nie zbiera się, gdy WeakReference odwołuje się do delegata?
Trudno mi wyjaśnić słowami. Dam przykład. Mam następujące klasy obiektu o nazwie 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;
}
}
Teraz, w moim głównym aplikacji, spróbuję odnieść się do sposobu TestMethod
w TestObject
poprzez WeakReference
. Intencją jest, aby TestObject
mógł zostać zebrany przez GC, gdy wszystkie twarde referencje zniknęły. To jest jak mój główny aplikacji wygląda następująco:
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();
}
to wyjście po uruchomieniu powyższy kod:
tu jest dziwne. W pierwszej linii, obj
można wydrukować "Hello 1"
, ponieważ została właśnie zainicjowana, a obj
przechowywał odwołanie do TestObject
. Wszystko dobrze. Następnie obj
ustawiono na null
z obj = null
, a GC został zmuszony do pobrania. Tak więc w drugim wierszu wyjścia, obj
jest true
, aby być zerowym. Na koniec na ostatniej linii, ponieważ GC zebrał obj
, oczekuję, że wyrzuci NullReferenceException
lub po prostu nic nie wydrukuje na wyjściu. Jednak wydrukowano to samo, co w pierwszym wierszu wydruku! Czy w tej chwili nie powinno już być zebrane przez GC TestObject
?!
To nasuwa pytanie, czy TestObject
, który został po raz pierwszy przechowywany w obj
, został później pobrany przez GC, czy nie, po ustawieniu obiektu obj na wartość null.
Gdybym przekazał cały obiekt do WeakReference
, tj. new WeakReference(obj)
, zamiast delegata do WeakReference
, działałby idealnie.
Niestety, w moim kodzie muszę przekazać delegatowi WeakReference
. Jak mogę ustawić poprawność działania WeakReference
, aby GC mógł zebrać obiekt przez odwołanie się do delegata?