3

我正在花一些时间学习弱引用在 C# 中的工作原理,并且遇到了这种奇怪的行为。

在下面的示例代码中,第一个测试通过,第二个测试失败。似乎您无法在构造之后但在创建对它的弱引用之前修改对象的实例,而无需停止弱引用以预期方式工作。

private class Simple
{
    public Simple() { X = "Hello"; }
    public string X { get; set; }
}

[Test]
public void CreatingWeakReferenceBeforeModifying()
{
    var a = new Simple();
    var aRef = new WeakReference(a);
    a.X = "World";  // First modification to a after creating reference
    a = null;
    GC.Collect();
    Assert.That(aRef.IsAlive, Is.False);  // This assertion passes
}

[Test]
public void CreatingWeakReferenceAfterModifying()
{
    var b = new Simple {X = "World"};  // First mod to b before creating ref
    var bRef = new WeakReference(b);
    b = null;
    GC.Collect();
    Assert.That(bRef.IsAlive, Is.False);  // This assertion fails
}

我在这里错过了什么吗?

4

1 回答 1

4

怀疑您只会在某些情况下看到这一点——尤其是在调试版本下,尤其是在调试器下。

这个说法:

var b = new Simple {X = "World"};

有效地:

var tmp = new Simple();
tmp.X = "World";
var b = tmp;

因此,即使您设置b为 null,堆栈上仍然有一个局部变量引用该对象。

在优化的场景中运行时,我希望 GC 注意到本地变量将永远不会被再次读取,并将其作为 GC 根忽略 - 但可能您运行它的方式不会让 GC 成为那样挑衅的。

于 2012-11-16T11:25:28.367 回答