是否需要使用stringbuilder?

时间:2013-10-25 15:10:39

标签: c# string clr stringbuilder cil

我们都知道连接字符串会导致效率问题,特别是在循环中。我被教导使用StringBuilder来防止这些问题。

所以这个:

str += someotherstring

变成这样:

StringBuilder sb = new StringBuilder();   
sb.AppendLine(someotherstring);

但我的理解是,.NET framework 3.5及更高版本中的CLR足够智能,可以为这两种方法输出相同的IL。那么我是否应该在我的团队代码审查中强制执行stringbuilder呢?

编辑:我认为 Servy 在评论中砸了一下:

  

在编译时连接多个 known 字符串时就是这种情况。因此,当在编译时连接多个字符串时,不需要使用SB。在编译时连接多个字符串 unknown 时,它无法执行此操作

4 个答案:

答案 0 :(得分:7)

不,这不总是正确的。如果你检查了How to improve string concatenation performance in Visual C#

,我不会
  

但是,.NET Framework包含一个StringBuilder类   针对字符串连接进行了优化。它提供了相同的好处   在C / C ++中使用字符数组,以及自动增长   缓冲区大小(如果需要)并跟踪长度。例子   本文中的应用程序演示了StringBuilder的用法   class并将性能与连接进行比较。

当您在代码传递中执行多个循环或分叉时,最好使用StringBuilder。

同时检查此

StringBuilder is not always faster – Part 1 of 2

  

这段代码在我的电脑上运行了1484毫秒:

for (int i = 0; i <= 1000000; i++)  { 
    // Concat strings 3 times using StringBuilder 
    StringBuilder s = new StringBuilder(); 
    s.Append(i.ToString()); 
    s.Append(i.ToString()); 
    s.Append(i.ToString());  }
     

这个使用传统串联的情况稍微少一些   时间(1344毫秒):

for (int i = 0; i <= 1000000; i++)  { 
    // Concat strings 3 times using traditional concatenation 
    string s = i.ToString(); 
    s = s + i.ToString(); 
    s = s + i.ToString();  }
     

以上数据表明StringBuilder只能开始更快地运行   一旦连接数超过3。

Tim发表的评论中有很好的链接,其中提到

Rules of Thumb

  

那么,什么时候应该使用StringBuilder,何时应该使用   字符串连接运算符?

     
      
  • 当你在一个非平凡的循环中连接时,绝对使用StringBuilder - 特别是如果你不确定(在编译时)   时间)你将通过循环进行多少次迭代。 例如,   一次读取一个文件,随时建立一个字符串   使用+ =运算符可能会导致自杀。
  •   
  • 当你可以(可读地)指定需要在一个语句中连接的所有内容时,绝对使用连接运算符。   (如果要连接的数组,请考虑调用   String.Concat显式 - 如果需要分隔符,则为String.Join。)
  •   
  • 不要害怕将文字分成几个连接位 - 结果将是相同的。你可以通过将长文字分成几行来提高可读性,例如,没有任何伤害   性能
  •   
  • 如果您需要连接的中间结果,而不是提供下一次连接迭代,   StringBuilder不会帮助你。例如,如果你积累了   来自名字和姓氏的全名,然后添加第三个名称   一条信息(昵称,也许)到最后,你只会   如果您不需要(名字+,请使用StringBuilder)   姓氏)​​字符串用于其他目的(正如我们在示例中所做的那样)   创建一个Person对象)。
  •   
  • 如果你只是要进行一些连接,并且你真的想在单独的语句中进行这些连接,那么哪种方式并不重要   你走。哪种方式更有效将取决于数量   连接所涉及的字符串的大小,以及它们的顺序   连接在一起。如果你真的相信这段代码是一个   性能瓶颈,简介或基准两种方式。
  •   

答案 1 :(得分:2)

  

但是我的理解是.NET框架3.5和中的CLR   后来很聪明,可以为两种方法输出相同的IL。

不。这不是必需的。您不能依赖编译器在循环中优化它。使用StringBuilder也更好,因为它在字符串连接中肯定会更好,并提供更好的可读性。

答案 2 :(得分:0)

例如,当您连接任意数量的字符串值时,将使用

StringBuilder。如果这种情况听起来像您的情况那么,是的,您应该强制使用StringBuilder

答案 3 :(得分:0)

.NET中的字符串是不可变的。一旦构建,它们以后就无法修改。如果你想修改一个字符串,你需要从旧字符串中创建一个新字符串并丢弃旧字符串。

另一方面,StringBuilder可以被认为是可变字符串。在构造内容后更改其内容是可能的,并且不需要分配整个新对象。

在比较使用StringBuilder和字符串连接执行类似操作所花费的时间时,通常不会出现不同的性能特征。效果更加间接:虽然字符串连接可能产生大量短期临时对象,但StringBuilder却没有。因此,使用StringBuilder可以显着减少托管堆上的内存压力,从而减少昂贵的垃圾收集的必要性。

这完全取决于您的申请,我不会尝试提供任何通用建议。执行大量字符串操作的应用程序(如Web服务器)需要更多关注而不需要。如果你理解字符串和StringBuilder是如何不同的,那么你应该做出明智的决定。如有疑问:个人资料。但一定要对GC周期进行分析。

相关问题