下面的示例程序表现出令人惊讶的最终行为:
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(使用前将#替换为@)