登录
/
注册
首页
论坛
其它
首页
科技
业界
安全
程序
广播
Follow
园子
关于
博客
发1篇日志+1圆
记录
发1条记录+2圆币
发帖说明
登录
/
注册
账号
自动登录
找回密码
密码
登录
立即注册
搜索
搜索
关闭
CSDN热搜
程序园
精品问答
技术交流
资源下载
本版
帖子
用户
软件
问答
教程
代码
VIP申请
网盘
联系我们
道具
勋章
任务
设置
我的收藏
退出
腾讯QQ
微信登录
返回列表
首页
›
业界区
›
业界
›
C#会重蹈覆辙吗?系列之4:华而不实的C#析构器 ...
C#会重蹈覆辙吗?系列之4:华而不实的C#析构器
[ 复制链接 ]
仰翡邸
2025-5-29 19:28:45
前段时间去鸟国出差,颠倒黑白,碌碌无为,疏于写博,请大家理解。下面继续前贴7月《C与C++社区混战,C#会重蹈覆辙吗?》的讨论。这次要谈的是C#的析构器的问题。这是C#中非常华而不实的一个设计,不必要,且常常误导很多C#er,且是.NET性能问题的常见陷阱地带。下面逐项讨论:
1.C#析构器是一个丑陋的语法糖
C#析构器(即Destructor)本质上是对Finalize方法的一个override。既然是对Finalize方法的override,那就大大方方让程序员去override 根类Object的Finalize方法好了。可是,C#设计师们首先搞了一个析构器,接着又在编译器里面把父类的Finalize方法隐藏掉(你去override的时候,告诉你父类没有Finalize方法)。但是编译完后,在IL代码中又告诉你override了父类中的Finalize方法,而你写的析构器却不翼而飞!
我在编程语言历史上看到很多语法糖,有些语法糖华丽,有些语法糖冗赘。但是还从没见过如此弯弯绕的语法糖!
2. C#析构器偏离了析构器原有的意思
析构器自在各编程语言中造始,便有以下两大基本含义:
(a) 回收对象内部开销的动态内存以及各种资源
(b) 回收具有确定性时刻,比如delete对象时,或者栈cleanup时。
可是C#将Finalize强扭成析构器后,彻底丢失掉前面两大基本含义,既无法回收动态内存,又无法确定时刻调用(只能等GC在猴年马月想起来才调用)。而只用于回收资源(而即便连这个任务也完成得很差,参见3.C#析构器不能完成其设计的初衷)。这使得很多沿用以前析构器概念的程序员经常犯如下错误,比如:
class MyClass {
object field;
~MyClass() { field=null; } //既不必要,也严重损伤性能
}
class MyClass {
object field;
~MyClass() { GC.Collect(); } //既不必要,也严重、严重损伤性能
}
3. C#析构器不能完成其设计的初衷
前面说过C#析构器主要用于释放对象的资源(非托管资源),而非内存。
但很不幸,对于C#析构器这个唯一的任务,它却不能很好地胜任。因为C#析构器(也就是Finalize方法)是由GC调用的,而GC只会在猴年马月想起来才调用(回收对象之前的一轮回收),往往延误了对象资源的释放——而对象资源是非常昂贵的。 如果真的这样来做的话,项目会倒大霉——比如我们以前的一个项目,有部分程序员在析构器中释放一些native内存,最后导致内存暴涨——用户抱怨下来,最后一调试发现原来都是在析构器惹得祸——这些析构器半天没有被GC调用!
实际上,C#设计者在后来意识到这个问题了,于是又推出来一个Dispose方法(即Dispose模式)来让用户显式释放资源。然后又推荐程序员在Dispose里面GC.SuppressFinalize(). 即屏蔽析构器。
既然Dispose能将事情(确定性地释放非托管资源)做好,析构器如此没用,当初设计它干吗?这是再典型不过的多余设计了!
4. C#析构器会带来严重的性能障碍
a) C#析构器会将对象的代标记(Generation)拖大,使得对象更难以被GC回收,给GC造成更大性能负担。
b) 析构器本身释放资源较晚,造成资源紧张,影响系统性能。
c) 析构器执行需要一个单独的线程开销,该线程的执行(必须时间很短)需要其他线程停止,也是一个性能负担。
这也是为什么C#推荐实现Dispose,不推荐实现析构器的原因。因为析构器的性能代价太大。可能中小项目的开发人员感受不到这一点,但我相信做过大型项目的朋友,对C#析构器的性能问题会有非常深的体会。
综上,C#析构器是C#设计师们纯粹为了炫耀自己华丽语法糖、而不小心又失了手艺、一个拙劣的设计。
[ Update: ]
听从网友的建议,把文章中“脑抽型、臭脚、sucks”等“骂街”的话删除掉了。写这些“骂街”的话实在是昨晚文章写到深处,肝火旺盛,想到某些言论,情不自禁而已。并非我就是“泼妇”,今天一看自己昨晚的言论确实火力太猛,接受大家的意见,改正语言风格,希望下面坚持“技术讨论不骂街“的原则。如果我有时候情不自禁做不到,希望大家监督指点,我会及时改过自新,重新做人
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复
使用道具
举报
提升卡
置顶卡
沉默卡
喧嚣卡
变色卡
千斤顶
照妖镜
相关推荐
那些年搞不懂的高深术语——依赖倒置•控制反转•依赖注入•面向接口编程
如何优雅的使用RabbitMQ
分布式锁1 Java常用技术方案
浅谈我对DDD领域驱动设计的理解
游戏编程十年总结(下)
【前端性能】高性能滚动 scroll 及页面渲染优化
验证码对抗之路及现有验证机制介绍
从零开始入门 K8s | 手把手带你理解 etcd
中文写程序,何陋之有?
NHibernate之旅(2):第一个NHibernate程序
公司的中场
FFmpeg开发笔记(六十二)Windows给FFmpeg集成H.266编码器vvenc
Android 系统缺陷不完全点评
谈谈如何从本质上理解sql语句, 存储过程,ORM之间的联系和取舍。
[一步一步MVC]第一回:使用ActionSelector控制Action的选择
.net环境下跨进程、高频率读写数据
第二个iPhone应用程序:“Say Hello”
从零开始学习jQuery (十一) 实战表单验证与自动完成提示插件
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
回复
本版积分规则
回帖并转播
回帖后跳转到最后一页
签约作者
程序园优秀签约作者
发帖
仰翡邸
2025-5-29 19:28:45
关注
0
粉丝关注
12
主题发布
板块介绍填写区域,请于后台编辑
财富榜{圆}
敖可
9986
森萌黠
9996
堵赫然
9996
4
凶契帽
9996
5
处匈跑
9996
6
柴古香
9996
7
背竽
9996
8
里豳朝
9994
9
恐肩
9992
10
都硎唷
9992
查看更多