如何明智地使用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;
你在内存中有三个单独的strings
: a
, result
的旧值和新值。 当然,如果只连接有限数量的strings
这是绝对没问题的。 如果你在一个for
循环迭代大集合的时候这样做,可能会成为一个问题。
在这些情况下, StringBuilder
类提供了改进的性能。 而不是创build新的strings
来存储连接的结果,它使用同一个对象。 所以如果你使用stringBuilder.Append(a);
你永远不会有“ result
旧值”。
这个记忆效率当然有价格。 当仅连接less量strings
, StringBuilder
速度通常较低,因为与不可变string
类相比,它具有更多开销。
有一件事要记住,当你需要中间string时, StringBuilder
会变得不那么高效,因为调用.ToString()
会创build一个string
的新副本。
原因是因为strings
是不可变的。 当连接一个string
你创build一个新的string
。 所以,当你需要连接许多strings
你会创build很多objects
。 这在内存方面没有多less成本,因为每个string
都使用一次。 但它确实为GC
提供了额外的工作。
然而StringBuilder
每次都使用相同的object
,但是这样做是以易用性为代价的。