垃圾收集器获胜;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()  {}
}

有人能向我解释一下这种行为吗?或者更好的是,有人知道如何确保对象被收集垃圾吗?

附言:如果以前有人问过类似的问题,请耐心等待。我只检查了标题中使用的问题。

垃圾收集器获胜;t收集使用创建的对象

using不是为了强制垃圾收集,而是为了确保调用dispose。Dispose允许您释放非垃圾收集的资源,如文件句柄。当c良好并且准备就绪时,垃圾回收就会发生。

我怀疑using语句可能引入了一个local。在调用GC.Collect之前,使用ildasm查看函数中对对象的所有引用是否都已真正清除。还要尝试将using位放在一个单独的函数中,该函数返回弱引用。

您的两个测试用例不完全相同。在using语句的末尾,将调用资源的Dispose方法,但该方法不会设置为null。调用Dispose不一定要调用析构函数。

标记&像在.NET中使用的一样,sweep GC是不具有确定性的。即使由GC.Collect()调用,也不能保证它真的运行。

此外,using子句与垃圾回收没有任何关系。If只是对其目标对象调用Dispose()。