当对象完成但尚未收集垃圾时的弱参照行为

这是关于在C#/ .NET中进行对象最终化和集合的学术问题。 背景阅读是C#语言规范自动内存管理的第3.9节。

当没有对对象的显式引用时,它可能变为垃圾回收。 它变得“有资格进行破坏”。 在将来的某个时刻(例如,如果强制进行垃圾收集),将运行对象的析构函数。

在析构函数中,如果保存对该对象的引用,该对象将被最终确定,但不符合收集条件。 这可能导致对象处于已完成但尚未收集的状态。 规范的第3.9节就是一个例子。

此时,该对象仍然存在,因为它尚未被垃圾收集。 但是,引用该对象的WeakReference报告IsAlive值为false,表示该对象已被收集。

核心问题是 – IsAlive属性真正报道的是什么? 我们知道我们不能信任此属性的值true,因为在读取之后该值很快就会变为false。 但是false值是值得信赖的,并且意味着(根据文档)表明该对象已被垃圾收集。 那么在这种情况下IsAlive属性告诉我们什么呢? 不严格对象是否被垃圾收集,因为我们认为对象处于最终但未收集的状态。

这是一个显示行为的示例。

public class Dog { public static Dog KeepDogRef; public string Name { get; set; } public Dog(string name) { Name = name; } ~Dog() { Console.WriteLine("Dog destructor for " + Name + " called"); Dog.KeepDogRef = this; } public void Bark() { Console.WriteLine(Name + " : Woof"); } } 

和主程序的代码。 如果您运行代码,您将看到原始WeakReference报告IsAlive为false,即使我们重新构建对象。

  static void Main() { Dog dog = new Dog("Bowser"); WeakReference dogRef = new WeakReference(dog); // Unref Bowser, now eligible for destruction dog = null; GC.Collect(); GC.WaitForPendingFinalizers(); // Bowser no longer alive Console.WriteLine(string.Format("Object still alive: {0}", dogRef.IsAlive)); // Bowser alive again Dog newRef = Dog.KeepDogRef; newRef.Bark(); } } 

如果您阅读了WeakReference所有文档,很明显可以使用多种类型的弱引用。 默认是生成一个简短的弱引用。 但是你也可以创建弱的参考,专门解释复活场景。

TrackResurrection的文档:

获取当前WeakReference对象引用的对象在完成后是否被跟踪的指示。

如果为true,则弱引用是一个长弱引用,并且为WeakReference构造函数中的trackResurrection参数指定了true。

所以我要说在解释IsAlive属性之前你必须要理解这部分弱引用。