为什么不在退出应用程序之前运行(最后)c#终结器?

时间:2015-01-20 11:46:25

标签: c# finalizer

我有一个c#Console App(visual studio 2013 express),如下:

class Program
{
    static void Main(string[] args)
    {
        var max = 1;

        for (int i = 0; i < max; i++)
        {
            var inherited = new GCInherited(i);

            //you can not run, if I only create this class
            //var gcbase = new GCBase(i);

            //if explicit set to null, the finalizer started:
            //inherited = null;
        }
        GC.Collect(2);
        GC.WaitForPendingFinalizers();

        //so do not run
        //GC.WaitForFullGCApproach(-1);
        //GC.WaitForFullGCComplete(-1);

        Console.ReadLine();
    }
}

class GCInherited : GCBase
{
    public GCInherited(int nr) : base(nr) { }

    ~GCInherited() { Console.WriteLine("GCInherited finalizer ({0})", this.nr); }
}

class GCBase
{
    public int nr { get; private set; }

    public GCBase(int nr) { this.nr = nr; }

    ~GCBase() { Console.WriteLine("GCBase finalizer"); }
}
  • 如果max=1,则在退出程序之前,终结器仅在按下回车键后运行。
  • 如果max=2,则0的终结器在输入之前运行(如预期的那样),并且终结器1仅在输入之后运行。
  • 如果取消注释inherited=null,则在按Enter键之前会运行所有终结器。

问题出现了:为什么?

我会非常感激任何想法。

github repo of source

1 个答案:

答案 0 :(得分:0)

你期待垃圾收集的错误。

陈述你的观点:

如果max = 1,则在退出程序之前,仅在按下回车键后运行终结器。 你的for循环运行一次,因此引用GCInherited为0作为数字。由于在程序中调用了垃圾收集,因此这是对继承的对象的引用。

如果max = 2,则在输入之前运行0的终结器(如预期的那样),并且仅在输入之后运行1的终结器。 同样的thign在这里发生,除了事实上第一次引用数字0的GCInherited丢失了,因为你通过初始化一个新的GCInherited数字1覆盖它并将其写入继承。

如果uncomment inherited = null,则在按Enter键之前运行所有终结器。 当然,因为不再有任何GcInherited对象的引用。