我理解String和StringBuilder之间的区别(StringBuilder是可变的),但两者之间有很大的性能差异吗?

我正在工作的程序有很多case驱动的字符串追加(500+)。使用StringBuilder是更好的选择吗?


当前回答

使用字符串进行连接会导致运行时复杂度达到O(n^2)的量级。

如果使用StringBuilder,需要复制的内存就会少得多。使用StringBuilder(int capacity),如果您可以估计最终字符串的大小,则可以提高性能。即使不精确,也可能只需要将StringBuilder的容量增加几倍,这也有助于提高性能。

其他回答

作为一般的经验法则,如果我必须设置字符串的值不止一次,或者如果字符串有任何追加,那么它需要是一个字符串构建器。在了解字符串构建器之前,我曾经看到我过去编写的应用程序具有巨大的内存足迹,而且似乎一直在不断增长。将这些程序更改为使用字符串构建器可以显著减少内存使用。现在我对琴弦制造者发誓。

这个基准测试表明,当组合3个或更少字符串时,常规连接更快。

http://www.chinhdo.com/20070224/stringbuilder-is-not-always-faster/

StringBuilder可以在内存使用方面做出非常显著的改进,特别是在将500个字符串加在一起的情况下。

考虑下面的例子:

string buffer = "The numbers are: ";
for( int i = 0; i < 5; i++)
{
    buffer += i.ToString();
}
return buffer;

内存中发生了什么?创建以下字符串:

1 - "The numbers are: "
2 - "0"
3 - "The numbers are: 0"
4 - "1"
5 - "The numbers are: 01"
6 - "2"
7 - "The numbers are: 012"
8 - "3"
9 - "The numbers are: 0123"
10 - "4"
11 - "The numbers are: 01234"
12 - "5"
13 - "The numbers are: 012345"

通过将这5个数字加到字符串的末尾,我们创建了13个字符串对象!其中12个是无用的!哇!

StringBuilder fixes this problem. It is not a "mutable string" as we often hear (all strings in .NET are immutable). It works by keeping an internal buffer, an array of char. Calling Append() or AppendLine() adds the string to the empty space at the end of the char array; if the array is too small, it creates a new, larger array, and copies the buffer there. So in the example above, StringBuilder might only need a single array to contain all 5 additions to the string-- depending on the size of its buffer. You can tell StringBuilder how big its buffer should be in the constructor.

StringBuilder明显更高效,但除非您进行大量的字符串修改,否则无法看到这种性能。

下面是给出性能示例的一小段代码。正如您所看到的,只有当您进入大型迭代时,您才真正开始看到主要的性能提升。

正如您所看到的,20万次迭代花费了22秒,而使用StringBuilder的100万次迭代几乎是瞬间完成的。

string s = string.Empty;
StringBuilder sb = new StringBuilder();

Console.WriteLine("Beginning String + at " + DateTime.Now.ToString());

for (int i = 0; i <= 50000; i++)
{
    s = s + 'A';
}

Console.WriteLine("Finished String + at " + DateTime.Now.ToString());
Console.WriteLine();

Console.WriteLine("Beginning String + at " + DateTime.Now.ToString());

for (int i = 0; i <= 200000; i++)
{
    s = s + 'A';
}

Console.WriteLine("Finished String + at " + DateTime.Now.ToString());
Console.WriteLine();
Console.WriteLine("Beginning Sb append at " + DateTime.Now.ToString());

for (int i = 0; i <= 1000000; i++)
{
    sb.Append("A");
}
Console.WriteLine("Finished Sb append at " + DateTime.Now.ToString());

Console.ReadLine();

以上代码的结果:

开头字符串+在28/01/2013 16:55:40。 完成字符串+在28/01/2013 16:55:40。 开头字符串+在28/01/2013 16:55:40。 完成字符串+在28/01/2013 16:56:02。 开始Sb追加在28/01/2013 16:56:02。 完成Sb的追加在28/01/2013 16:56:02。

StringBuilder is probably preferable. The reason is that it allocates more space than currently needed (you set the number of characters) to leave room for future appends. Then those future appends that fit in the current buffer don't require any memory allocation or garbage collection, which can be expensive. In general, I use StringBuilder for complex string concatentation or multiple formatting, then convert to a normal String when the data is complete, and I want an immutable object again.

是的,StringBuilder在对字符串执行重复操作时提供了更好的性能。这是因为所有的更改都是对单个实例进行的,因此它可以节省大量时间,而不是像String那样创建一个新实例。

String Vs Stringbuilder

字符串 系统命名空间下 不可变(只读)实例 当价值发生持续变化时,性能下降 线程安全的 StringBuilder(可变字符串) 在系统。文本名称空间 可变的实例 显示更好的性能,因为对现有实例进行了新的更改

强烈推荐dotnet mob文章:c#中的String Vs StringBuilder。 相关堆栈溢出问题:字符串时的可变性 在c#中没有改变?