当前位置 > 首页 > Asp.net

《Effective C#》读书笔记——条目16:避免创建非必要的对象<.NET资源管理>

2012-11-27 9:12:00来源:Asp.net

  我们知道:C#是一门虚拟机语言,C#编译器首先将C#代码编译成IL代码,运行程序时CLR(Common Language Runtime,公共语言运行时)通过调用JIT(just-in-time Compiler即时编译器)来将IL代动态即时编译成可执行的机器码。GC(Garbage Collector,垃圾收集器)自动为我们的应用程序进行内存管理的分配和释放,(具体参见:了解.NET 内存管理机制),以一种高效的方式来移除内存中的垃圾对象,不过不管有多高效,分配和销毁在堆上的对象总会花费掉时间。

  如果我们在一个方法中创建了过多的引用对象,会对应用程序的性能产生严重的影响。因此我们应该遵守下面的一些规则,可以尽量的降低GC的工作量。

 

阅读目录:

      1.将常用的局部变量提升为成员变量

      2.为常用的类型实例提供静态对象

      3.为不可变类型提供可变的创建对象

      小节

 

1.将常用的局部变量提升为成员变量

   所有的引用类型,包括那些局部变量,都会分配到堆上。在函数退出后,函数内的所有局部变量都会立即变成垃圾对象。所以我们可以得出结论:

若是某个引用类型(值类型无所谓)的局部变量用于被频繁调用的例程中,那么应该将其提升为成员变量。这既有助于减轻GC的负担,也可以提升程序运行的效率。

 在GUI编程中一个常见的错误就是:在窗体的Paint处理函数中创建GDI(Graphics Device Interface,图形设备接口)对象,如下:

1 protected override void OnPaint(PaintEventArgs e)
2 {
3 using (Font myFont = new Font("Arial", 10.0f))
4 {
5 e.Graphics.DrawString(DateTime.Now.ToString(), myFont, Brushes.Black, new Point(0, 0));
6 }
7 base.OnPaint(e);
8 }

 

OnPaint()将会被非常频繁的调用,每次调用都会创建一个Font对象,而包含的内容完全和上一次一样。所以GC需要每次都为你清扫这些垃圾,严重影响了应用程序的效率。其实我们完全可以将Font对象提升为成员变量,是每次窗体重绘时能够重用该Font对象:

1 private readonly Font myFont = new Font("Arial", 10.0f);
2
3 protected override void OnPaint(PaintEventArgs e)
4 {
5 e.Graphics.DrawString(DateTime.Now.ToString(), myFont, Brushes.Black, new Point(0, 0));
6
7 base.OnPaint(e);
8 }

 将常用的局部变量提升为成员变量之后,程序无需每次重绘时生成垃圾对象,减轻了GC的负担,也提升了程序的效率。不过这里有一个小小的限制:将实现了IDisposable接口的局部变量提升为成员变量,那么这个成员变量依附类本身也需要实现IDisposable接口。

 

2.为常用的类型实例提供静态对象

  静态成员变量可以让引用类型在类的各个实例中共享。我们可以通过提供了一个类,存放某个类型常用的实例的单例对象,这样可以避免创建重复的对象。.NET Framework 的类库中就有很多这样的做法:Brushes类包含了一系列的静态Brush对象,每个都包含了一种常用的颜色。它们的简要实现如下:

1 private static Brush blackBrush;
2 public static Brush Black
3 {
4 get

  • re: 线程安全的Generic Dictionary

    2007-2-10 4:56:00

    在枚举的过程中修改了集合,这个问题,我也经常碰到,也都是像你这样解决的。只是,我不明白你写这篇文章的意义所在,我倒是挺关心这个线程安全的,可否跟我说说?谢谢了。 你回复就可以了,我会接收到邮件

  • (原創) 為什麼VB有Dim obj As Foo = New Foo()這種語法? (初級) (Visual BASIC)

    2007-7-17 1:23:00

    摘要: 以前在寫VB/VBScript時,一直不了解為什麼VB提供兩套New語法,Dim obj As New Foo()和Dim obj As Foo = New Foo(),尤其後者,重複兩次c

  • August 14, 2007 - Huntsville - North Alabama talk on .NET Orcas

    2007-6-23 14:44:00

    Ill be at the HUNTUG meeting on August 14th, 2007 to talk about .NET Orcas and some of the things c

  • 判断Request.UrlReferrer对火狐无效??

    2009-12-14 12:18:00

    阅读: 279 评论: 6 作者: Showker 发表于 2009-12-14 10:48 原文链接 我现在有一个页面default.aspx,我想做一个功能就是如果是通过window.

  • .Net三层架构--讨论(下篇)

    2009-5-25 8:06:00

    我是提倡分层的,但是,个人认为,一个系统的组成,没有三层那么简单 对于前篇,我的立场没有表达清楚,在此表达歉意, COM 这个可以说是微软帮助程序员跳出编程噩梦,具有里程碑意义的构

  • 分享一些共享的特效源代码

    2009-7-20 14:45:00

    大部分是从网络上收集的,有动态云效果、火焰效果、水波效果。对其中的原始代码进行了很多恰当的优化,改善了程序的运行速度和降低CPU使用率。 动态云效果,可以使用这个加上滚动字幕或者背景音乐做出

  • Application vs. AppDomain

    2007-9-3 4:15:00

    A question was asked on a forum that I frequent which I thought was worth writting a blog about.

  • re: 用Baidu搜索&ldquo;sb&rdquo;,居然第一个就是Google?!

    2007-2-28 5:04:00

    @Jeffrey Zhao 我也只能查到sb是safe browsing,但到底如何safe呢? Cat Chen 2007-02-28 01:11 发表评论

  • 基于Web的仿WF工作流设计器

    2007-3-18 12:35:00

    微软的WF是个不错的工作流开发平台,相对于开源的工作流实现而言,它的设计器不可谓不漂亮(当然,也和我以前看到的连线式设计器大不一样),上个星期突然冒出个想法,能不能在Web页面上实现一个类似的工作流

  • 微软挖角IBM ,怎么看?

    2007-1-23 9:21:00

    微软这几年在不断挖角,现在又挖角WebSphere之父Don Ferguson,具体参见 Father of WebSphere leaves IBM to join Microsoft 。现在微软