5

这是一个关于 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();   
    }
}
4

1 回答 1

7

如果您阅读 的所有文档WeakReference,很明显有不止一种类型的弱引用可用。默认是产生一个的弱引用。但是您也可以创建专门针对复活场景的长弱引用。

从文档中TrackResurrection

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

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

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

于 2012-12-17T14:05:54.303 回答