在.net析构函数中重新创建对“this”的有根引用是否合法?

时间:2009-03-03 14:32:33

标签: c# .net garbage-collection destructor finalizer

在.net中写下以下内容是否合法?

   public class A
    {
        public int i = 0;
        ~A()
        {
            Aref = this;
        }
    }


    public static A Aref;
    static void Main(string[] args)
    {
        Aref = new A();
        int gen = GC.GetGeneration(Aref);
        Aref = null;
        GC.Collect(gen, GCCollectionMode.Forced);
        GC.WaitForPendingFinalizers();
        Console.WriteLine(Aref.i);
        Console.ReadLine();
    }

它正常工作并按预期将“0”写入控制台,但我想知道它是否能保证始终有效。

有人知道幕后发生了什么吗?

3 个答案:

答案 0 :(得分:8)

它被称为复活,它是合法的。谷歌的“.net对象复活”(以及类似的术语),你会发现像:

这样的东西

Resurrection and the .NET Garbage collector

Object Resurrection

确保这些僵尸物品不会回来并试图吃掉你的大脑或其他东西。像所有的死灵法一样,这是危险的东西。 (主要是因为类层次结构中较高的终结器可以释放一些必要的资源。另请注意,如果对象被“未引用”,则终结器将不会再次运行,除非您调用GC.ReRegisterForFinalize。)< / p>

答案 1 :(得分:1)

它起作用,因为第一个垃圾收集不收集实例。它只是安排实例运行终结器。终结器然后为实例创建一个新的根,因此当下一个集合发生时,实例实际上是root的,因此不能进行收集。

你应该非常小心这一点。如果使用终结器来确保放置一个对象,这实际上违反了协议,因为一次性模式表明如果在处置后使用它,则处置的实例应抛出ObjectDisposedException。

答案 2 :(得分:0)

垃圾收集器将对象分为三组:

  1. 那些仍然存活的,因为最后检查一个有根参考的引用存在于终结队列之外;
  2. 那些需要删除,因为在任何地方都不存在有根引用;
  3. 那些需要最终确定的,因为在终结队列中存在有根引用,但在其他任何地方都没有。
除非在任何地方都没有root权限引用,否则无法删除对象。最终确定是删除前的一个独特阶段;请注意,当一个对象被注册用于最终化时,它所引用的所有对象都将被保护而不被删除,但不会被终止。