垃圾收集器获胜;t收集使用创建的对象
本文关键字:创建 对象 收集器 获胜 | 更新日期: 2023-09-27 17:58:26
我想测试对象引用是否保存不正确,并编写了一个总是失败的测试。我将测试简化为以下行为:
[Test]
public void ScopesAreNotLeaking()
{
WeakReference weakRef;
Stub scope = null;
using (scope = new Stub())
{
weakRef = new WeakReference(scope);
}
scope = null;
GC.Collect();
GC.WaitForPendingFinalizers();
Assert.That(weakRef.Target, Is.Null);
}
然而,这个测试在不使用的情况下也能做到这一点,它通过了:
[Test]
public void ScopesAreNotLeaking()
{
WeakReference weakRef;
Stub scope = new Stub();
weakRef = new WeakReference(scope);
scope = null;
GC.Collect();
GC.WaitForPendingFinalizers();
Assert.That(weakRef.Target, Is.Null);
}
使用的存根类很简单:
class Stub : IDisposable
{
public void Dispose() {}
}
有人能向我解释一下这种行为吗?或者更好的是,有人知道如何确保对象被收集垃圾吗?
附言:如果以前有人问过类似的问题,请耐心等待。我只检查了标题中使用的问题。
using不是为了强制垃圾收集,而是为了确保调用dispose。Dispose允许您释放非垃圾收集的资源,如文件句柄。当c良好并且准备就绪时,垃圾回收就会发生。
我怀疑using语句可能引入了一个local。在调用GC.Collect
之前,使用ildasm查看函数中对对象的所有引用是否都已真正清除。还要尝试将using位放在一个单独的函数中,该函数返回弱引用。
您的两个测试用例不完全相同。在using
语句的末尾,将调用资源的Dispose
方法,但该方法不会设置为null。调用Dispose不一定要调用析构函数。
标记&像在.NET中使用的一样,sweep GC是不具有确定性的。即使由GC.Collect()
调用,也不能保证它真的运行。
此外,using子句与垃圾回收没有任何关系。If只是对其目标对象调用Dispose()。