为什么要在对象上调用终结器

2024-03-06

下面的示例程序表现出令人惊讶的最终行为:

class Something
{
    public void DoSomething()
    {
        Console.WriteLine("Doing something");
    }
    ~Something()
    {
        Console.WriteLine("Called finalizer");
    }
}

namespace TestGC
{
    class Program
    {
        static void Main(string[] args)
        {
           var s = new Something();
           s.DoSomething();
           GC.Collect();
           //GC.WaitForPendingFinalizers();
           s.DoSomething();
           Console.ReadKey();
        }
    }
}

如果我运行该程序,打印的内容是:

Doing something
Doing something
Called finalizer

这看起来正如预期的那样。因为在调用之后有对 s 的引用GC.Collect(), s 不是垃圾。

现在从该行中删除注释//GC.WaitForPendingFinalizers();再次构建并运行该程序。

我希望输出不会发生任何变化。这是因为我读到了如果发现对象是垃圾并且它有终结器,则它将被放入终结器队列。由于对象不是垃圾,因此不应该将其放入终结器队列似乎是合乎逻辑的。因此,注释掉的行不应该执行任何操作。

然而,该程序的输出是:

Doing something
Called finalizer
Doing something

有人可以帮助我理解为什么终结器被调用吗?


我无法在我的笔记本电脑上重现该问题,但您的DoSomething方法不使用对象内的任何字段。这意味着该对象可以被终结即使在DoSomething在跑.

如果您将代码更改为:

class Something
{
    int x = 10;

    public void DoSomething()
    {
        x++;
        Console.WriteLine("Doing something");
        Console.WriteLine("x = {0}", x);
    }
    ~Something()
    {
        Console.WriteLine("Called finalizer");
    }
}

...那我怀疑你会always see DoingSomething在“Called Finalizer”之前打印两次 - 尽管最终的“x = 12”可能在“Called Finalizer”之后打印。

基本上,最终确定可能会有些令人惊讶 - 我very我很少发现自己使用它,并且会鼓励您尽可能避免终结器。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么要在对象上调用终结器 的相关文章

随机推荐