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

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


当前回答

StringBuilder是可取的,如果你正在做多个循环,或分叉在你的代码传递…然而,对于PURE性能,如果你可以使用SINGLE字符串声明,那么性能就会更好。

例如:

string myString = "Some stuff" + var1 + " more stuff"
                  + var2 + " other stuff" .... etc... etc...;

更有表现力吗

StringBuilder sb = new StringBuilder();
sb.Append("Some Stuff");
sb.Append(var1);
sb.Append(" more stuff");
sb.Append(var2);
sb.Append("other stuff");
// etc.. etc.. etc..

在这种情况下,可以认为StringBuild更易于维护,但性能并不比单个字符串声明更好。

但是十有八九……使用字符串构建器。

另一方面:string + var也比string的性能更好。格式方法(通常)在内部使用StringBuilder(如果有疑问…检查反射器!)

其他回答

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。

是的,性能差异是显著的。请参阅KB文章“如何在Visual c#中提高字符串连接性能”。

我总是试着先编写清晰的代码,然后再优化性能。这比反过来做要容易得多!但是,看到了两者在我的应用程序中的巨大性能差异后,我现在更仔细地考虑了一下。

幸运的是,在代码上运行性能分析相对简单,可以看到您在哪些地方花费了时间,然后在需要的地方修改它以使用StringBuilder。

为了澄清Gillian所说的4弦,如果你有这样的东西:

string a,b,c,d;
 a = b + c + d;

那么使用字符串和加号运算符会更快。这是因为(就像Eric指出的Java一样),它在内部自动使用StringBuilder(实际上,它使用StringBuilder也使用的原语)

但是,如果你正在做的事情接近:

string a,b,c,d;
 a = a + b;
 a = a + c;
 a = a + d;

然后你需要显式地使用一个StringBuilder。. net在这里不会自动创建一个StringBuilder,因为这毫无意义。在每行的末尾,"a"必须是一个(不可变的)字符串,因此它必须在每行上创建和释放一个StringBuilder。为了提高速度,你需要使用相同的StringBuilder,直到你完成构建:

string a,b,c,d;
StringBuilder e = new StringBuilder();
 e.Append(b);
 e.Append(c);
 e.Append(d);
 a = e.ToString();

在. net中,StringBuilder仍然比追加字符串快。我很确定在Java中,它们只是在附加字符串时在底层创建了一个StringBuffer,所以没有真正的区别。我不确定为什么他们还没有在。net中这样做。

StringBuilder减少了分配和赋值的数量,代价是使用了额外的内存。如果使用得当,它可以完全消除编译器需要一遍又一遍地分配越来越大的字符串,直到找到结果为止。

string result = "";
for(int i = 0; i != N; ++i)
{
   result = result + i.ToString();   // allocates a new string, then assigns it to result, which gets repeated N times
}

vs.

String result;
StringBuilder sb = new StringBuilder(10000);   // create a buffer of 10k
for(int i = 0; i != N; ++i)
{
   sb.Append(i.ToString());          // fill the buffer, resizing if it overflows the buffer
}

result = sb.ToString();   // assigns once