加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 18:26:51 所属栏目:百科 来源:网络整理
导读:我有一个测试,我预计通过,但垃圾收集器的行为不是我推测的: [Test]public void WeakReferenceTest2(){ var obj = new object(); var wRef = new WeakReference(obj); wRef.IsAlive.Should().BeTrue(); //passes GC.Collect(); wRef.IsAlive.Should().BeTrue
我有一个测试,我预计通过,但垃圾收集器的行为不是我推测的:
[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.

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

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

解决方法

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

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

[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();
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读