4

在 .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',但我想知道它是否保证始终工作。

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

4

3 回答 3

8

这叫做复活,是合法的。谷歌搜索“.net object resurrection”(以及类似的术语),您会发现以下内容:

Resurrection 和 .NET 垃圾收集器

对象复活

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

于 2009-03-03T14:44:23.630 回答
1

它之所以有效,是因为第一次垃圾收集不收集实例。它只是安排实例运行其终结器。终结器然后为实例创建一个新的根,所以当下一次收集发生时,实例实际上是根的,因此不适合收集。

你应该非常小心这个艰难的。如果使用终结器来确保释放对象,这实际上违反了协议,因为可释放模式表示,如果在释放后使用已释放的实例,则应抛出 ObjectDisposedException。

于 2009-03-03T14:50:09.000 回答
0

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

  1. 那些还活着的,因为最后检查了一个根引用存在于终结队列之外;
  2. 那些需要删除的,因为任何地方都不存在根引用;
  3. 那些需要最终确定的,因为根引用存在于终结队列中,但没有其他地方。
除非任何地方都没有根引用,否则无法删除对象。定稿是删除前的一个独特阶段;请注意,当一个对象被注册为终结时,它直接或间接引用的所有对象都将受到保护,不会被删除,但不会被终结。

于 2010-12-02T08:06:13.033 回答