我对使用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
不值得使用,不是吗?
答案 0 :(得分:97)
修改 immutable 结构(如string
)必须通过复制结构来完成,并且由此消耗更多内存并减慢应用程序的运行时间(同时增加{{} 1}}时间等...)。
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或更多{{1}时,在时间和内存消耗方面似乎更有效}}
不良做法:
StringBuilder
精细练习用法(注意使用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");
答案 1 :(得分:12)
string
是不可变类。您无法修改它,只能创建新的strings
。
因此,当您撰写result += a;
时,内存中有三个单独的strings
:a
,旧值result
和新值。当然,如果你只连接有限数量的strings
,这绝对没问题。如果你在迭代大型集合的for
循环中执行此操作,则可能会出现问题。
StringBuilder
类在这些情况下提供了改进的性能。而不是创建新的strings
来存储连接的结果,它使用相同的对象。因此,如果您使用stringBuilder.Append(a);
,则永远不会具有“result
的旧值”。
这种内存效率当然需要付出代价。当只连接少量strings
StringBuilder
时,速度通常效率较低,因为与不可变string
类相比,它具有更多的开销。
要记住的一件事是,当您需要中间字符串时,StringBuilder
可能效率降低,因为在其上调用.ToString()
会创建string
的新副本。
答案 2 :(得分:1)
原因是因为strings
是不可变的。连接string
时,您会创建一个新的string
。因此,当您需要连接多个strings
时,您会创建大量objects
。这在内存方面不会花费太多,因为每个string
使用一次。但它确实为GC
提供了额外的工作。
StringBuilder
每次都使用相同的object
,但这样做会牺牲易用性。