如何明智地使用 StringBuilder?

首先,我对使用 StringBuilder类有点困惑:

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

但是创建 StringBuilder实例以避免创建新的 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是不值得的,不是吗?

94647 次浏览

原因是 strings是不可变的。当连接一个 string时,您创建一个新的 string。因此,当您需要连接许多 strings时,您会创建许多 objects。这在内存方面花费不多,因为每个 string只使用一次。但它确实为 GC提供了额外的工作。

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

string不可变类。您不能修改它,只能创建新的 strings

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

在这些情况下,StringBuilder类提供了更好的性能。它没有创建新的 strings来存储连接的结果,而是使用相同的对象。因此,如果你使用 stringBuilder.Append(a);,你永远不会有等价的“旧值的 result”。


当然,这种内存效率是有代价的。当只连接少量的 strings时,StringBuilder在速度方面往往效率较低,因为与不可变的 string类相比,它有更多的开销。


需要记住的一点是,当需要中间字符串时,StringBuilder的效率可能会降低,因为对它调用 .ToString()会创建 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()函数,但是,只有当串联使用6-7个或更多的 strings时,StringBuilder似乎在时间和内存消耗方面更有效率。

错误的用法:

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");