Когда вы вызываете TryGetTarget
по слабой ссылке, предполагая, что указанный объект еще не был собран, вы получаете сильную ссылку на этот объект.Вы делаете это 3 раза в своем коде: p1
, p2
и p3
являются сильными ссылками на объект.Когда сборщик мусора запускается - автоматически или в вашем случае, когда вы принудительно собираете мусор - эти сильные ссылки не позволят собрать объект.
Вот версия, которая работает:
void Main()
{
var person = new Person();
WeakReference<Person> weak = new WeakReference<Person>(person);
person = null;
for (int i = 0; i < 10; i++)
{
Console.WriteLine($"{i}\t{TestReference(weak)}");
Thread.Sleep(100);
}
GC.Collect();
Console.WriteLine(TestReference(weak));
}
class Person
{
private int mI = 3;
public int MI { get => mI; set => mI = value; }
}
bool TestReference(WeakReference<Person> weak)
{
if (weak.TryGetTarget(out Person p))
{
p = null;
return true;
}
return false;
}
Обратите внимание, чтомы ни в коем случае не сохраняем сильную ссылку на объект в течение более чем нескольких циклов, и к тому времени, когда сборщик мусора запускается, нет сильных ссылок на объект, поэтому объект собирается.
Даже вхотя этот код, если я закомментирую строку p = null;
, сборщик мусора может не собрать объект. Попробуйте и посмотрите.
Мораль этой истории такова: когда вы получаете сильныйссылка из WeakReference<>
, всегда обнуляет сильную ссылку, когда вы закончите с ней.