Effective C# Item16:尽量减少内存垃圾
虽然.NET提供了垃圾回收机制,可以对托管的资源进行管理,但是创建对象和销毁对象本身,也是要花费时间的,特别是对于引用类型来说,频繁的创建和销毁引用类型的对象,对性能来说,是非常不好的。
我们可以采取一些措施,来改善这种情况。
首先,来看下面的代码。

1 protected override void OnPaint( PaintEventArgs e )
2 {
3 // Bad. Created the same font every paint event.
4 using ( Font MyFont = new Font( "Arial", 10.0f ))
5 {
6 e.Graphics.DrawString( DateTime.Now.ToString(),
7 MyFont, Brushes.Black, new PointF( 0,0 ));
8 }
9 base.OnPaint( e );
10 }
我们可以将上面代码中的Font对象重构为类的成员变量,这样在调用OnPaint()方法时,就可以重用Font对象。

1 private readonly Font _myFont =
2 new Font( "Arial", 10.0f );
3
4 protected override void OnPaint( PaintEventArgs e )
5 {
6 e.Graphics.DrawString( DateTime.Now.ToString( ),
7 _myFont, Brushes.Black, new PointF( 0,0 ));
8 base.OnPaint( e );
9 }
然后,针对平时一些常用的引用类型,我们可以构建该类型的静态实例,这样可以保证类型只被实例化一次。另外,为了提升性能,可以对类型的实例实行延迟加载的策略,只在用到的时候,才会被加载。
最后,当我们构造常量类型的固定值时,例如string,因为对string类型执行+=操作,就相当于重新创建一个string实例,这样在构造的过程中,会产生大量string中间实例,为了减少string实例的数目,我们可以使用stringbuilder来初始化。
总结:垃圾收集器在管理应用程序所使用的内存方法非常有效,但是,记住创建和销毁对象仍然需要花费时间。我们应该避免创建过多的对象;不要创建不需要的对象。也要避免在局部方法内部创建多个引用类型的对象,相反,我们应该考虑将局部变量提升为类型的成员变量,或者为类型中的绝大多数常用类型创建一些静态实例,最后,对于具有常量性的类型,我们应该考虑为它们创建一个支持可变的生成类型。
作者:李潘
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通