c#我的析构函数没有被调用?

Uur*_*Uur 3 c# destructor finalize

我有这个简单的代码,并试图调用析构函数,但我不能称之为:(

我知道GarbageCollector会在必要时运行,所以我使用了GC.WaitForPendingFinalizers(); 但它也没有用.

这是我的代码:

class Program
    {
        static void Main(string[] args)
        {
            Calculator calculator = new Calculator();
            Console.WriteLine("{0} / {1} = {2}", 120, 15, calculator.Divide(120, 15)

            GC.Collect();
            GC.WaitForPendingFinalizers();

            Console.WriteLine("Program finishing");                           
        }

  }

class Calculator
    {

        // Constructor
        public Calculator()
        {
            Console.WriteLine("Calculator being created");
        }

        // Public Divide method
        public int Divide(int first, int second)
        {
            return first / second;
        }

        // Destructor
        ~Calculator()
        {
            Console.WriteLine("Destructor is called");

        }

    }
Run Code Online (Sandbox Code Playgroud)

这是我的输出:

正在创建的计算器

120/15 = 8

程序完成

我究竟做错了什么?为什么我看不到"析构函数被调用"?

Eri*_*ert 12

寿命一个的局部变量控制的声明它的局部变量范围内的激活的寿命.所以你的当地人还活着,直到主要结束.仅这一点就足以解释为什么没有收集它,但这里有一些细微之处我们应该更深入地探索.

可以通过各种机制来扩展生命周期,包括通过lambda,迭代器块,异步方法等捕获外部变量.

在抖动可以证明这样做对单线程控制流没有影响的情况下,允许缩短寿命.(您可以使用KeepAlive以确保在您必须避免它的情况下不会发生这种缩短.)

在您的情况下,允许运行时注意到本地永远不会再次读取,将其标记为早期死亡,从而孤立对该对象的引用,然后将其收集并最终确定.它不要求这样做,显然,你的情况,其实不然.

正如另一个答案所正确指出的那样:如果GC检测到调试器正在运行,它会故意抑制此优化,因为在检查包含调试器中对它的引用的变量时收集对象是一种糟糕的用户体验!

让我们考虑一下我关于缩短生命期的陈述的含义,因为我认为你可能还没有完全掌握这些含义.

  • 允许运行时注意到ctor永远不会访问它.

  • 允许运行时注意到divide从不访问它.

  • 允许运行时注意到因此从未实际读取和使用本地

  • 因此,允许该对象在其生命周期的任何时刻都不会在GC中生根.

  • 这意味着允许垃圾收集器在构造函数之前运行终结器.

GC和终结器在他们自己的线程上运行,记住; 操作系统可以挂起主线程并在任何时候切换到gc和终结器线程,包括在分配器运行之后但在控制传递给构造函数之前.

绝对疯狂的事情被允许发生在你写的那个场景中; 没有运行的终结器是你问题最少的!它可以运行,这是可怕的.

如果您没有立即明白这一事实,那么您就没有业务撰写终结者.编写正确的终结器是C#中最难做的事情之一.如果您不是CLR垃圾收集器语义的所有细节的专家,那么您不应该编写终结器.

有关如何编写终结器的更多想法,请参阅我关于该主题的系列文章,从这里开始:

https://ericlippert.com/2015/05/18/when-everything-you-know-is-wrong-part-one/

  • 老实说,使用现代工具集,你根本不需要写一个终结器,*永远*.任何需要一个finiazer的东西都可以用自定义或预先制作的'SafeHande`包裹起来.请参阅文章"[IDisposable:您的母亲从未告诉过您关于资源重新分配的内容](https://www.codeproject.com/Articles/29534/IDisposable-What-Your-Mother-Never-Told-You-About)"for斯蒂芬克莱里写的伟大指南. (5认同)
  • @Uur:我目前正在讨论是否要删除FB中PHP/Hack代码中析构函数的用法,所以如果你来到这里,你可能没有机会编写析构函数.:-) (3认同)