我花了一些时间来学习弱引用在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
}
我错过了什么吗?
答案 0 :(得分:4)
我怀疑你只能在某些情况下看到这一点 - 特别是在调试版本下,特别是在调试器下。
本声明:
var b = new Simple {X = "World"};
实际上是:
var tmp = new Simple();
tmp.X = "World";
var b = tmp;
因此,即使您将b
设置为null,堆栈上仍然存在一个局部变量,该变量具有对象的引用。
在优化方案中运行时,我希望GC注意到局部变量永远不会再次读取,并将其忽略为GC根目录 - 但可能是你的方式运行它不让GC变得那么激进。