У меня есть класс, который держится за делегата, чтобы потом что-то лениво оценить.
Как только я оценил это, вызвав делегата, я очищаю ссылку на делегата, надеясь, чточто это будет иметь право на сбор.В конце концов, он мог бы держаться за мир локальных переменных, если бы он был создан как анонимный метод.
Я пытался создать модульный тест, чтобы проверить это, но, похоже, он не сработалЯ планировал, вместо этого кажется, что мои предположения о WeakReference
(которые я использовал здесь для целей тестирования), или какое-то другое предположение, не выдерживают критики.
Взгляните на этот код, который выможет работать в LINQPad
void Main()
{
WeakReference wr;
Lazy<int> l;
CreateTestData(out wr, out l);
wr.IsAlive.Dump(); // should be alive here
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
wr.IsAlive.Dump(); // and alive here as well
l.Value.Dump(); // but now we clear the reference
GC.Collect(); // so one of these should collect it
GC.WaitForPendingFinalizers();
GC.Collect();
wr.IsAlive.Dump(); // and then it should be gone here
GC.KeepAlive(l);
}
void CreateTestData(out WeakReference wr, out Lazy<int> l)
{
Func<int> f = () => 10;
wr = new WeakReference(f);
l = new Lazy<int>(f);
}
public class Lazy<T>
{
private Func<T> _GetValue;
private T _Value;
public Lazy(Func<T> getValue)
{
_GetValue = getValue;
}
public T Value
{
get
{
if (_GetValue != null)
{
_Value = _GetValue();
_GetValue = null;
}
return _Value;
}
}
}
Я предполагал, что:
- Независимо от сборки DEBUG, отладчик подключен, поскольку я создал делегат в отдельном методеот которого я возвращаюсь, не должно быть ничего, что удерживало бы делегата, кроме объектов
WeakReference
и Lazy<T>
- Если я прошу объект
Lazy<T>
отказаться от своей ссылки на делегата, которыйуменьшит ссылки только до той, которую WeakReference
удерживает до - , а затем принудительно выполнит полную сборку мусора, предполагая, что если единственная оставленная ссылка - это ссылка в
WeakReference
- Тогда тего делегат будет собран, и мой
WeakReference
будет означать, что объект больше не существует
Ожидается, что выходной код будет (с комментариями):
true // not gc'ed after construction
true // not gc'ed after full GC, still beind held by Lazy<T>
10 // value from calling delegate
false // but is now gc'ed, Lazy<T> no longer has a reference to it
Но вместо этого получается:
true
true
10
true
Может кто-нибудь пролить свет на то, что мне здесь не хватает?