C# 析构函数全详解:原理+实战+避坑
很多学过 C 的同学初学 C# 都会踩一个大坑试图用 C 的析构思维写 C# 代码。在 C 中析构函数是确定性执行的对象销毁立刻触发但在 C# 中析构函数完全是另一套逻辑乱用会导致内存泄漏、程序卡顿、资源残留等问题。今天这篇博文一次性讲透C# 析构函数是什么、什么时候执行、怎么写、怎么用、以及90%人都会犯的错误附带全套可运行代码。一、什么是 C# 析构函数1. 核心定义析构函数终结器是类的特殊方法由CLR 垃圾回收器GC自动调用作用是兜底释放非托管资源。简单记住两句话托管资源 GC 自动管不用你操心非托管资源 GC 管不了靠析构函数兜底2. 标准语法规则语法特征极强一眼就能识别以~波浪号开头 类名无返回值、无参数、无访问修饰符不能加 public/private一个类只能有一个析构函数不支持重载3. 最简入门代码示例using System; namespace DestructorDemo { public class Student { // 构造函数创建对象时执行 public Student() { Console.WriteLine(对象创建构造函数执行); } // 析构函数GC回收对象前自动执行 ~Student() { Console.WriteLine(对象销毁析构函数执行); } } class Program { static void Main(string[] args) { // 创建对象 Student stu new Student(); // 主动置空让GC可以回收 stu null; // 手动触发垃圾回收仅测试用项目中禁止写 GC.Collect(); GC.WaitForPendingFinalizers(); } } }运行结果对象创建构造函数执行对象销毁析构函数执行 注意日常开发绝对不要手动写 GC.Collect()此处仅为测试让大家直观看到析构函数效果。二、析构函数 VS 构造函数图文对比逻辑为了方便大家理解我用最直白的生命周期逻辑展示生命周期流程图解【代码执行 new】→ 构造函数初始化资源 ↓ 【对象使用中】→ 执行业务逻辑 ↓ 【对象无引用、闲置】→ GC扫描标记 ↓ 【垃圾回收】→ 析构函数清理资源 ↓ 【对象彻底销毁】核心区别对照表对比维度构造函数析构函数执行时机new 对象时确定性执行GC回收时不确定时机调用者开发者代码主动调用CLR 垃圾回收器自动调用作用初始化字段、开辟资源兜底释放非托管资源数量可多个、可重载只能1个、不可重载手动调用支持完全不支持三、重中之重托管资源 非托管资源能不能用好析构函数核心就在于分清这两种资源1. 托管资源GC 自动回收由 .NET 框架管理的资源GC 会自动清理不需要析构函数例string、List、数组、自定义类对象 等2. 非托管资源GC 管不了必须兜底操作系统原生资源.NET 无法自动识别回收必须手动释放/析构兜底例文件流、数据库连接、网络套接字、IntPtr 非托管内存、窗口句柄核心结论 没有非托管资源的类坚决不写析构函数只会增加 GC 性能开销四、企业级标准写法Dispose 释放模式纯析构函数有致命问题执行时机太晚、不确定。 所以 .NET 官方规范IDisposable 析构函数 双保险模式用户主动 using/Dispose立刻释放所有资源高效、及时用户忘记释放析构函数兜底防止内存泄漏完整可运行实战代码using System; namespace DestructorDemo { // 实现释放接口 public class FileResource : IDisposable { private IntPtr _unmanagedHandle; // 模拟非托管资源句柄 private bool _isDisposed false; // 构造函数占用非托管资源 public FileResource() { Console.WriteLine(获取非托管资源句柄); _unmanagedHandle (IntPtr)10086; // 模拟资源赋值 } // 公共释放方法给开发者手动调用 public void Dispose() { Dispose(true); // 告诉GC资源已释放无需执行析构函数 GC.SuppressFinalize(this); Console.WriteLine(手动释放资源完成跳过析构执行); } // 核心释放逻辑 protected virtual void Dispose(bool isManualDispose) { if (_isDisposed) return; // 主动释放时可清理托管资源 if (isManualDispose) { Console.WriteLine(清理托管资源); } // 无论手动/GC回收必须清理非托管资源 if (_unmanagedHandle ! IntPtr.Zero) { Console.WriteLine(释放非托管资源句柄); _unmanagedHandle IntPtr.Zero; } _isDisposed true; } // 析构函数GC兜底执行 ~FileResource() { Dispose(false); Console.WriteLine(析构函数兜底释放完成); } } class Program { static void Main(string[] args) { // using 语法糖出作用域自动调用Dispose using (var file new FileResource()) { Console.WriteLine(正在使用资源...); } Console.WriteLine(程序执行结束); } } }运行结果获取非托管资源句柄 正在使用资源... 清理托管资源 释放非托管资源句柄 手动释放资源完成跳过析构执行 程序执行结束可以看到手动 Dispose 成功后析构函数不会执行性能最优五、析构函数 4 大高频误区避坑必看误区1C# 析构 C 析构错误C 析构确定性执行C# 析构完全随机程序退出都可能不执行正确需要及时释放的资源一律用using Dispose误区2析构函数中操作托管对象错误GC 回收顺序不可控其他托管对象可能已经被回收直接报空引用异常正确析构中只处理非托管资源误区3所有类都写析构函数错误无非托管资源时写析构会让对象进入终结队列降低GC回收效率正确无原生资源不写析构函数误区4手动调用析构函数错误C# 禁止手动调用 ~类名() 和 Finalize()正确资源释放统一用 Dispose六、总结博文核心干货析构函数是GC 自动兜底的非托管资源清理方法执行时机不确定语法~类名()无参无返回值唯一不可重载托管资源不用管非托管资源必须靠Dispose析构双保险业务开发优先使用using 语法糖杜绝手动 GC 操作无原生非托管资源坚决不写析构函数避免性能损耗码字不易欢迎点赞收藏后续持续更新 C# 底层原理、.NET 性能优化、实战避坑干货

相关新闻

零基础实现 Windows 全局标题栏毛玻璃特效:DWMBlurGlass 安装与调优完整指南

零基础实现 Windows 全局标题栏毛玻璃特效:DWMBlurGlass 安装与调优完整指南

零基础实现 Windows 全局标题栏毛玻璃特效:DWMBlurGlass 安装与调优完整指南 【免费下载链接】DWMBlurGlass Add custom effect to global system title bar, support win10 and win11. 项目地址: https://gitcode.com/gh_mirrors/dw/DWMBlurGlass 你有没有过…

2026/10/26 13:40:31 阅读更多 →
深入解析电子商务网站前台建设:打造高转化率的线上 storefront 实战指南

深入解析电子商务网站前台建设:打造高转化率的线上 storefront 实战指南

在这个流量红利逐渐见顶、竞争白热化的时代,很多老板或者刚入行的电商运营同学问我:“为什么我的推广做得风生水起,钱烧了不少,结果转化率却惨不忍睹?” 其实,答案往往不在后台的数据优化,也不在站外的广告投放,而是在最前端、最直观的那一块——也就是我们的电子商务网…

2026/10/24 17:55:59 阅读更多 →
Node 后端实战 · Serverless 导出 CSV 总超时?用 Queue + R2 异步任务彻底解决

Node 后端实战 · Serverless 导出 CSV 总超时?用 Queue + R2 异步任务彻底解决

Node 后端实战 Serverless 导出 CSV 总超时?用 Queue R2 异步任务彻底解决 各位看官,今天聊一个在 Serverless / 边缘运行时里几乎绕不开、但又特别容易写错的需求:大批量数据导出。 我这个后端是跑在 Cloudflare Workers 上的&#xff0…

2026/10/25 17:46:31 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/26 12:00:21 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/27 4:06:49 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/27 7:21:53 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/26 12:00:21 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/27 6:20:47 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/27 4:06:50 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/27 13:55:19 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/27 7:21:50 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/26 8:34:37 阅读更多 →