好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

StringBuilder,String.concat(),String+String 哪一个效率高

StringBuilder,String.concat(),String+String 哪一个效率高

今天,我在写C#代码时,突然发现一个最熟悉的陌生人 —— string.Format。在写C#代码的日子里,与它朝夕相伴,却没有真正去了解它。只知道在字符串比较多时,用它比用加号进行字符串连接效率更高(当然也更方便)。可是却从来没有问过为什么?

在生活中也有类似的现象,与你朝夕相处、你最熟悉的人,你往往不会进一步去了解她(他),你已经习惯了她(他),你认为你已经太了解她(他)了。。。真的是这样吗?这值得去思考。。。

博问中的一个问题 ——  StringBuilder,String.concat(),String+String 哪一个效率高?   激发了我的好奇心,想一探string.Format的究竟,而且在开发中也正好遇到一个字符串连接的问题。

了解.NET世界中的东西其实很简单,只要通过工具反编译出相应的.NET类库代码,我们来看看string.Fomat的代码:

     public   static   string  Format( string  format,  object  arg0,  object  arg1,  object   arg2)
    {
        if  (format ==  null  )
          throw   new  ArgumentNullException( "  format  "  );
        return   string .Format((IFormatProvider)  null  , format, arg0, arg1, arg2);
    } 

实际调用的是另外一个签名的string.Format:

     public   static   string  Format(IFormatProvider provider,  string  format,  params   object  [] args)
    {
        if  (format ==  null  || args ==  null  )
          throw   new  ArgumentNullException(format ==  null  ?  "  format  "  :  "  args  "  );
      StringBuilder stringBuilder  =  new  StringBuilder(format.Length + args.Length *  8  );
      stringBuilder.AppendFormat(provider, format, args);
        return  (( object  ) stringBuilder).ToString();
    } 

哦,原来用的就是StringBuilder(也许你早就知道了),string.Format只是StringBuilder的改装精简版。

既然是StringBuilder,它必然无法避免一个影响StringBuilder性能的问题 —— 初始化容量(capacity)的问题,string.Format是如何解决的呢?从上面的代码一眼就可以看出,初始化容量是这么计算出来的:

format.Length + args.Length *  8 

从这个计算公式可以看出,假设需要format的字符串是10个,如果这10字符串累加起来的字符数不超过80,就能发挥StringBuilder的最佳性能;否则,StringBuider需要扩容,从而带来性能损失。

所以,对于大字符串,string.Format不是最佳选择。

那最佳选择是什么?还是StringBuilder,只不过要自己写代码计算初始化容量。分享一下今天我们在实际开发中使用的代码:

 var  bodyFormat =  "  <span id=\"comment_body_{0}\">{1}</span><br/>  "  ;                        
  var  diggFormat =  "   <a href=\"javascript:void(0);\" onclick=\"voteComment({0},'Digg')\">支持({2})</a>  "  ;
  var  buryFormat =  "   <a href=\"javascript:void(0);\" onclick=\"voteComment({0},'Bury')\">反对({3})</a>  "  ;
  var  args =  new   string  []{ comment.ID.ToString(), comment.Body, comment.DiggCount.ToString(), comment.BuryCount.ToString() };
  //  计算初始化容量 
 int  capacity = bodyFormat.Length + diggFormat.Length +  buryFormat.Length;
  for  ( int  i =  0 ; i < args.Length; i++ )
{
    capacity  +=  args[i].Length;
}
  var  sb =  new   StringBuilder(capacity);
sb.AppendFormat(bodyFormat,args); 
sb.AppendFormat(diggFormat,args); 
sb.AppendFormat(buryFormat,args);
Post.Text  = sb.ToString();

这里没有使用string.Format,一是因为comment.Body的字符数会很多,string.Format分配的初始化容量不够。二是因为string.Format不能分批Fomat,格式字符串只能写在一起,造成格式字符串很长,也就是bodyFormat, diggFormat, buryFormat要拼成一个字符串。

麻烦主要在参数字符串(args)的长度计算,要将每个字符串的字符数进行累加。我们采用的方法是将所有参数放在string[]类型的变量中,通过遍历数组进行计算,然后将这个string[]类型的变量直接传给StringBuilder.AppendFormat(它支持的参数类型是object[])。

小结

写这篇博文不是为让你弃用string.Format,而是让你了解它所存在的限制,在某些性能要求极高的场景下,可以考虑到这个影响因素。

 

 

标签:  string_format_stringbuilder

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于StringBuilder,String.concat(),String+String 哪一个效率高的详细内容...

  阅读:47次