重现步骤:
这是我的代码:
using (TestClass test = new TestClass())
{
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
这就是我定义 TestClass 的方式:
public class TestClass : IDisposable
{
public void Dispose()
{
Dispose(true);
//GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
Console.WriteLine("Disposing TestClass.");
}
}
~TestClass()
{
Dispose(false);
Console.WriteLine("TestClass Finalizer called");
}
}
预期行为: 我确实看到“Disposing TestClass”按预期在 using 语句后打印,但我也希望在我运行 GC 命令后打印“TestClass Finalizer called”。我确保我跳过调用 GC.SuppressFinalize(this);在 Dispose 方法中。看起来已处置的变量即使在超出范围后也不会最终确定。它们似乎在程序退出前就完成了。
实际行为: 我只看到在 using 语句之后打印了“Disposing TestClass”,正如预期的那样,在 GC 命令之后没有看到“TestClass Finalizer called”。我只是在程序退出前才看到它。
这不是内存泄漏吗?
如果我将其转换为非一次性类并像下面这样更新代码,我确实会看到在 GC 命令之后调用终结器。
TestClass test = new TestClass();
test = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
public class TestClass
{
~TestClass()
{
Console.WriteLine("TestClass Finalizer called");
}
}
最佳答案
根据微软对 Object.Finalize Method ()
的描述
The exact time when the finalizer executes is undefined. To ensure deterministic release of resources for instances of your class, implement a Close method or provide a IDisposable.Dispose implementation.
将终结器视为第二道防线。如果程序未能调用 Close
或 Dispose
,则终结器将进行更改以纠正遗漏。
这仍将确保文件将在程序退出时关闭,例如,除非另一个终结器未退出并因此阻塞其他终结器,或者如果灾难性异常正在粗暴地终止程序。
这不是内存泄漏。如果内存变得稀缺,垃圾收集器 (GC) 可以在程序退出之前很久就决定释放资源并调用终结器。
关于c# - Finalizer 没有被一次性类型对象调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42329589/