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

Sea*_*ton 5 .net c# garbage-collection weak-references

这是关于在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");
    }
}
Run Code Online (Sandbox Code Playgroud)

和主程序的代码.如果您运行代码,您将看到原始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();   
    }
}
Run Code Online (Sandbox Code Playgroud)

Dam*_*ver 7

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

从以下文档TrackResurrection:

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

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

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

  • @SeanSexton:轻微纠正:一旦系统注意到该对象有资格进行收集但是存在终结器,弱引用就会失效,并将其添加到终结器方法应该在第一次机会运行的对象列表中.终结者通常会在不久之后运行,但可能会被任意延迟.一旦发现对象被放弃,任何以对象为目标的短"WeakReference"都将失效,无论终结器何时实际运行. (3认同)