这是关于在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();
}
}
答案 0 :(得分:7)
如果您阅读了WeakReference
的所有文档,很明显有多种类型的弱引用可用。默认设置是生成短弱引用。但您也可以创建长弱引用,专门用于复活方案。
来自TrackResurrection
的文档:
获取当前WeakReference对象引用的对象在完成后是否被跟踪的指示。
如果为true,则弱引用为长弱引用,并为
trackResurrection
构造函数中的WeakReference
参数指定true。
所以我要说在解释IsAlive
属性之前你必须要理解这部分弱引用。