重现步骤:
这是我的代码:
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");
}
}
预期行为:
我确实看到在using语句之后按预期方式打印了“处置TestClass”,但是我也希望在运行我的GC命令之后打印“调用TestClass的终结器”。我确保不跳过调用GC.SuppressFinalize(this);在Dispose方法中。看起来,即使已超出范围的变量也无法最终确定。它们似乎在程序退出之前就已完成。
实际行为:
我只看到在using语句之后按预期方式打印了“ Dispose TestClass”,但在GC命令之后看不到“ TestClass Finalizer被调用”。我只在程序退出前看到它。
这不是内存泄漏吗?
如果将其转换为非一次性类并更新如下代码,则可以看到在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 ()
的描述
终结器执行的确切时间是不确定的。为确保确定性地释放类实例的资源,请实现Close方法或提供IDisposable.Dispose实现。
将终结器视为第二道防线。如果程序无法调用Close
或Dispose
,则终结器将进行更改以更正省略。
这仍将确保,例如,文件将在程序退出时关闭,除非另一个终结器没有退出并因此阻塞了其他终结器,或者如果灾难性的异常残酷地终止了该程序。
这不是内存泄漏。如果内存不足,则垃圾回收器(GC)可以决定释放资源并在程序退出之前很长时间调用终结器。
关于c# - 终结器未调用一次性类型对象,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42329589/