改善C#程序的157个建议(连载1)

发表于:2011-10-12 09:37

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:陆敏技    来源:51Testing软件测试网采编

  注意:装箱之所以会带来性能损耗,因为它需要完成下面三个步骤:

  1)首先,会为值类型在托管堆中分配内存。除了值类型本身所分配的内存外,内存总量还要加上类型对象指针和同步块索引所占用的内存。

  2)将值类型的值复制到新分配的堆内存中。

  3)返回已经成为引用类型的对象的地址。

  第二个方面:避免分配额外的内存空间。对CLR来说,string对象(字符串对象)是个很特殊的对象,它一旦被赋值就不可改变。在运行时调用 System.String 类中的任何方法或进行任何运算(如“=”赋值、“+”拼接等),都会在内存中创建一个新的字符串对象,这也意味着要为该新对象分配新的内存空间。像下面的代码就会带来运行时的额外开销。

  • private static void NewMethod1()  
  • {  
  •     string s1 = "abc";  
  •     s1 = "123" + s1 + "456";    //以上两行代码创建了3个  
  •         //字符串对象,并执行了一次string.Contact方法  
  • }  
  • private static void NewMethod6()  
  • {  
  •     string re6 = 9 + "456";     //该代码发生一次装箱,并调  
  •         //用一次string.Contact方法  
  • }
  •   而在以下代码中,字符串不会在运行时拼接字符串,而是会在编译时直接生成一个字符串。

  • private static void NewMethod2()  
  • {  
  •     string re2 = "123" + "abc" + "456"; //该代码等效于  
  •         //string re2 = "123abc456";  
  • }  
  • private static void NewMethod9()  
  • {  
  •     const string a = "t";  
  •     string re1 = "abc" + a;     //因为a是一个常量,所以  
  •     //该行代码等效于 string re1 = "abc" + "t";  
  •     //最终等效于string re1 = "abct";  
  • }
  •   由于使用 System.String 类会在某些场合带来明显的性能损耗,所以微软另外提供了一个类型StringBuilder来弥补String的不足。

      StringBuilder并不会重新创建一个string 对象,它的效率源于预先以非托管的方式分配内存。如果StringBuilder 没有先定义长度,则默认分配的长度为16。当 StringBuilder 字符长度小于等于 16时,StringBuilder 不会重新分配内存;当 StringBuilder 字符长度大于16 小于 32时,StringBuilder 又会重新分配内存,使之成为 16的倍数。在上面的代码中,如果预先判断字符串的长度将大于16,则可以为其设定一个更加合适的长度(如32)。StringBuilder重新分配内存时是按照上次的容量加倍进行分配的。当然,我们需要注意,StringBuilder指定的长度要合适,太小了,需要频繁分配内存;太大了,浪费空间。

    32/3<123>
    《2023软件测试行业现状调查报告》独家发布~

    关注51Testing

    联系我们

    快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

    法律顾问:上海兰迪律师事务所 项棋律师
    版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
    投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

    沪ICP备05003035号

    沪公网安备 31010102002173号