咨询:C#中Finalizer未被调用的原因及解决办法
为什么C#终结器未被调用?
你的代码里终结器没被调用,核心原因有两个:
- 进程退出过快,GC未触发终结器:
Main方法执行完毕后进程立刻终止,CLR为了快速结束程序,不会等待垃圾回收器完成终结器的执行流程。此时Test对象虽然符合回收条件,但GC还没来得及处理它。 - CLR不保证终结器一定会执行:即使对象可被回收,CLR也没有承诺在任何场景下都会调用终结器,尤其是进程即将退出时,这种不确定性会被放大。
验证终结器的方法
如果想看到终结器执行,可以手动触发GC并等待终结器完成,修改代码如下:
using System; class Program { static void Main(string[] args) { Test test = new Test(); // 解除对象引用,让它成为垃圾回收目标 test = null; // 手动触发垃圾回收 GC.Collect(); // 等待所有pending的终结器执行完毕 GC.WaitForPendingFinalizers(); } } class Test { public Test() { Console.WriteLine("Start"); } ~Test() { Console.WriteLine("End"); } }
运行这段代码就能看到"End"输出了。
更可靠的资源释放方式
依赖终结器释放资源并不推荐,因为其执行时机不可控。如果需要确保资源被及时释放,应该实现IDisposable接口,配合using语句显式管理资源:
using System; class Test : IDisposable { public Test() { Console.WriteLine("Start"); } ~Test() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { // 释放托管资源(比如其他实现IDisposable的对象) } // 释放非托管资源 Console.WriteLine("End"); } } class Program { static void Main(string[] args) { using(var test = new Test()) { // 这里使用Test对象 } // 离开using块时自动调用Dispose,输出"End" } }
内容的提问来源于stack exchange,提问作者Emil Grigoryan
相关产品推荐
相关产品推荐

