我想测试不正确的对象引用并编写一个总是失败的测试。我将测试简化为以下行为:
[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() {}
}
有人可以解释一下这种行为,或者 - 甚至更好 - 有一个想法,如何确保对象被垃圾收集?
PS:如果之前有过类似的问题,请耐心等待。我只检查过标题中使用的问题。
答案 0 :(得分:5)
using不是为了强制垃圾收集而设计的,而是为了确保调用dispose。 Dispose允许您释放非垃圾收集的资源,如文件句柄。当c#很好并准备就绪时就会发生垃圾收集。
答案 1 :(得分:2)
我怀疑使用声明可能会引入本地。在调用GC.Collect
之前,使用ildasm查看函数中函数的所有引用是否都已真正清除。还要尝试将using位放在一个返回弱引用的单独函数中。
答案 2 :(得分:1)
标记&扫描GC,就像在.NET中使用的那样,不是确定性的。
即使被GC.Collect()
调用,也无法保证真正运行。
此外,using子句与垃圾收集没有任何关系。如果只是在其目标对象上调用Dispose()。
答案 3 :(得分:1)
您的两个测试用例并不完全相同。在using
语句结束时,将调用资源的Dispose
方法,但不会将其设置为null。调用Dispose不一定会调用析构函数。