如何明智地使用StringBuilder

我有点困惑使用StringBuilder类,第一:

string对象连接操作总是从现有string和新数据创build一个新对象。 一个StringBuilder对象维护一个缓冲区以适应新数据的连接。 如果空间可用,新的数据被附加到缓冲区的末尾; 否则,分配一个新的,更大的缓冲区,将来自原始缓冲区的数据复制到新的缓冲区,然后将新的数据附加到新的缓冲区。

但是,创buildStringBuilder实例的目的是为了避免创build一个新的String ? 这听起来像交易“一对一”。

 static void Main(string[] args) { String foo = "123"; using (StringBuilder sb = new StringBuilder(foo)) // also sb isn't disposable, so there will be error { sb.Append("456"); foo = sb.ToString(); } Console.WriteLine(foo); Console.ReadKey(); } 

为什么我不应该只使用

 += 

编辑:好吧,我现在知道如何重用StringBuilder一个实例(仍然不知道这是否正确与代码标准),但这是不值得用一个string ,不是吗?

string一样修改不可变的结构必须通过复制结构来完成,因此消耗更多的内存并减慢应用程序的运行时间(也增加了GC时间等)。

StringBuilder通过使用相同的可变对象进行操作来解决这个问题。

然而:

在编译时连接一个string如下:

 string myString = "123"; myString += "234"; myString += "345"; 

它实际上会编译成这样的东西:

 string myString = string.Concat("123", "234", "345"); 

这个函数比使用StringBuilder更快,因为进入函数的string的个数是已知的。

所以对于编译时已知的string连接,你应该更喜欢string.Concat()

至于未知数字的string如下面的情况:

 string myString = "123"; if (Console.ReadLine() == "a") { myString += "234"; } myString += "345"; 

现在,编译器不能使用string.Concat()函数,但是StringBuilder似乎只有在使用6-7个或更多的strings进行连接时才会在时间和内存消耗上更加高效。

糟糕的做法:

 StringBuilder myString = new StringBuilder("123"); myString.Append("234"); myString.Append("345"); 

良好的练习用法(注意if使用):

 StringBuilder myString = new StringBuilder("123"); if (Console.ReadLine() == "a") { myString.Append("234"); } myString.Append("345"); 

最佳实践用法(注意使用while循环):

 StringBuilder myString = new StringBuilder("123"); while (Console.ReadLine() == "a") { myString.Append("234"); //Average loop times 4~ or more } myString.Append("345"); 

一个string是一个不可变的类 。 你不能修改它,只能创build新的strings

所以当你写result += a; 你在内存中有三个单独的stringsaresult的旧值和新值。 当然,如果只连接有限数量的strings这是绝对没问题的。 如果你在一个for循环迭代大集合的时候这样做,可能会成为一个问题。

在这些情况下, StringBuilder类提供了改进的性能。 而不是创build新的strings来存储连接的结果,它使用同一个对象。 所以如果你使用stringBuilder.Append(a); 你永远不会有“ result旧值”。


这个记忆效率当然有价格。 当仅连接less量stringsStringBuilder速度通常较低,因为与不可变string类相比,它具有更多开销。


有一件事要记住,当你需要中间string时, StringBuilder会变得不那么高效,因为调用.ToString()会创build一个string的新副本。

原因是因为strings是不可变的。 当连接一个string你创build一个新的string 。 所以,当你需要连接许多strings你会创build很多objects 。 这在内存方面没有多less成本,因为每个string都使用一次。 但它确实为GC提供了额外的工作。

然而StringBuilder每次都使用相同的object ,但是这样做是以易用性为代价的。