StringBuilder比连接十几个字符串要慢,这是真的吗?

5
StringBuilder比连接数十个字符串要慢吗?编译器如何优化字符串连接,以便使用“+”连接数十个字符串比StringBuilder更好?
从一本书(由Ben Watson撰写)中得知:
字符串连接:对于已知(在编译时)数量的简单连接字符串,只需使用“+”运算符或String.Concat方法。这通常比使用StringBuilder更有效。string result = a + b + c + d + e + f; 在连接字符串数可变且可能大于几十个时再考虑使用StringBuilder。编译器会通过一种方式来优化简单的字符串连接,以减少内存开销。

11
赛跑你的马…… - Zohar Peled
3
为了达到清晰的编码目标,如果您设定了性能目标,那么应该写出清晰易懂的代码,并根据这些目标来衡量它的性能。如果达到目标,那就太好了。如果没有达到,可以看看重点代码是否需要重新编写。不要假设您可以学习一亿个小的“性能”规则并将其盲目应用于所有代码编写,以达到良好的性能。 - Damien_The_Unbeliever
1
@JonSkeet 啊,我没注意到我在“string”标签中,而不是“java”。 - Andy Turner
1
另一方面,如果某些模式比其他模式更有效,为什么不先使用它们(假设它们同样清晰)? - Yair Halberstadt
“过早优化是否真的是万恶之源?” - Fildor
2个回答

10

String.Concat更加高效,因为它在开始时就知道所有字符串的长度。因此,它可以分配一个具有恰当长度的单个缓冲区,将字符串复制到其中并返回该缓冲区。

StringBuilder必须分配一个小缓冲区,并在每次调用Append导致空间不足时重新分配和复制。最后一次调用ToString()也必须再次分配另一个缓冲区。

因此,在事先知道有多少字符串时,请使用String.Concat; 在不知道时,请使用StringBuilder

在C#中,对+运算符进行链式调用会自动转换为对String.Concat的单个调用。


2
如果您连接字符串常量编译器将自动执行连接操作。 - Hans Kesting

1
直接连接需要更少的对象和内存调用。因此,如果您在一个语句中连接所有字符串(没有任何文本处理),则速度更快。
在这种情况下,编译器可以计算新字符串的大小并分配内存并将所有字符复制到其中。因此,您只创建所需的对象。
如果您使用StringBuilder,则会使用额外的对象。如果您附加长字符串而不告诉StringBuilder在构造函数中使用巨大的缓冲区大小,则字符串生成器可能会执行多个内存分配和复制,因为它可能会多次运行标准内存分配。
如果您在循环中构建字符串,则StringBuild是更好的解决方案。在这种情况下,直接连接将在每次迭代中创建一个新对象和内存分配,而StringBuild仅使用一个内存分配(如果您在构造函数中使用正确的值)和仅两个对象。
但是很难说出运行时的情况。实现随时间变化而变化。因此,现在最佳实践可能在5年后成为最差实践。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接