如何明智地使用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 ,但是这样做是以易用性为代价的。