Мне кажется, что когда я использую класс WeakReference
в методе делегата класса объекта, класс объекта собирается GC, но есть еще одна его копия, находящаяся в WeakReference
?
Мне трудно объяснить словами. Я приведу пример. У меня есть следующий класс объектов с именем 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;
}
}
Теперь в моем основном приложении я пытаюсь сослаться на метод TestMethod
в TestObject
через WeakReference
. Цель состоит в том, чтобы сборщик мусора мог собрать TestObject
, когда все жесткие ссылки исчезнут. Вот как выглядит мое основное приложение:
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();
}
Это вывод, когда я запускаю приведенный выше код:
Вот что странно. В первой строке obj
мог напечатать "Hello 1"
, потому что он только что был инициализирован, а obj
содержал ссылку на TestObject
. Все верно. Затем obj
было установлено на null
с obj = null
, и сборщик мусора был вынужден собирать. Таким образом, во второй строке вывода obj
равно true
нулю. Наконец, в последней строке, поскольку сборщик мусора собрал obj
, я ожидаю, что он либо выдаст NullReferenceException
, либо просто ничего не напечатает на выходе. Однако на самом деле он напечатал то же самое, что и в первой строке вывода! Разве TestObject
уже не должен быть собран GC в этот момент?!
Возникает вопрос, были ли TestObject
, которые сначала хранились в obj
, были позже собраны GC или нет после того, как я установил для obj значение null.
Если бы я передал весь объект в WeakReference
, т.е. new WeakReference(obj)
, а не делегат в WeakReference
, все бы работало отлично.
К сожалению, в моем коде мне нужно передать WeakReference
делегата. Как я могу заставить WeakReference
работать правильно, чтобы GC мог собирать объект, только сославшись на делегата?