c# – 垃圾收集应该删除对象,但WeakReference.IsAlive仍然返回true

前端之家收集整理的这篇文章主要介绍了c# – 垃圾收集应该删除对象,但WeakReference.IsAlive仍然返回true前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个测试,我预计通过,但垃圾收集器的行为不是我推测的:
[Test]
public void WeakReferenceTest2()
{
    var obj = new object();
    var wRef = new WeakReference(obj);

    wRef.IsAlive.Should().BeTrue(); //passes

    GC.Collect();

    wRef.IsAlive.Should().BeTrue(); //passes

    obj = null;

    GC.Collect();

    wRef.IsAlive.Should().BeFalse(); //fails
}

在这个例子中,obj对象应为GC’d,因此我希望WeakReference.IsAlive属性返回false.@H_301_5@

看来,因为obj变量被声明在与GC.Collect相同的范围内,所以它没有被收集.如果我将对象声明和初始化移动到测试通过的方法之外.@H_301_5@

有没有人有任何技术参考文献或解释这个行为?@H_301_5@

解决方法

遇到同样的问题,我的测试通过无处不在,除了NCrunch之外(可能是您的情况下的任何其他工具).嗯.使用SOS进行调试会在测试方法调用堆栈上显示额外的根.我的猜测是,它们是禁用任何编译器优化的代码工具的结果,包括正确计算对象可达性的编译器优化.

这里的治疗是非常简单的 – 从来没有强调GC的方法和对活性的测试.这可以通过简单的帮助方法轻松实现.以下更改使您的测试用例与NCrunch通过,最初出现故障.@H_301_5@

[TestMethod]
public void WeakReferenceTest2()
{
    var wRef2 = CallInItsOwnScope(() =>
    {
        var obj = new object();
        var wRef = new WeakReference(obj);

        wRef.IsAlive.Should().BeTrue(); //passes

        GC.Collect();

        wRef.IsAlive.Should().BeTrue(); //passes
        return wRef;
    });

    GC.Collect();

    wRef2.IsAlive.Should().BeFalse(); //used to fail,now passes
}

private T CallInItsOwnScope<T>(Func<T> getter)
{
    return getter();
}
原文链接:https://www.f2er.com/csharp/96205.html

猜你在找的C#相关文章