Тестирование/проверка слабых сторон

Я хотел бы проверить, что код, устанавливающий WeakReference, случайно не содержит ссылки на ссылочный объект. (Здесь пример о том, как легко случайно это сделать.)

Означает ли это, что это лучший способ проверить ненадежные ссылки?

TestObject testObj = new TestObject();
WeakReference wr = new WeakReference(testObj);

// Verify that the WeakReference actually points to the intended object instance.
Assert.Equals(wr.Target, testObject);

// Force disposal of testObj;
testObj = null;
GC.Collect();
// If no strong references are left to the wr.Target, wr.IsAlive will return false.
Assert.False(wr.IsAlive);

Ответ 1

Я связался с Microsoft об этом и узнал/подтвердил, что:

  • GC.Collect() принудительно блокирует сбор мусора.
  • Когда GC.Collect() запускается, он не будет таинственным образом пропускать объекты, имеющие доступ к коллекции. Предсказуемые правила соблюдаются для определения того, какие объекты собирать. Пока вы работаете с пониманием этих правил (например, как обрабатываются завершаемые объекты), вы можете принудительно уничтожить определенный объект, хотя память, используемая уничтоженным объектом, может быть освобождена или не может быть освобождена.

Дополнительная информация в моем блоге: Может ли быть сделана сборка мусора .Net?

Ответ 2

Я сделал это только вчера. Здесь я должен был добавить, чтобы сбор произошел до вашего последнего утверждения:

        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.WaitForFullGCComplete();
        GC.Collect();

Если после этого .IsAlive по-прежнему верен, вероятно, там все еще есть сильная ссылка.

Кстати. Обязательно НЕ проверяйте .IsAlive, когда вы получаете доступ к своей цели WeakReference. Чтобы избежать условия гонки между проверкой .IsAlive и .Target, сделайте следующее:

var r = weakRef.Target AS Something;
if (r != null)
{
    ... do your thing
}