string
和StringBuilder
之间有什么区别?
此外,理解的例子是什么?
答案 0 :(得分:96)
string
实例是不可变的。创建后无法更改它。任何看似更改字符串的操作都会返回一个新实例:
string foo = "Foo";
// returns a new string instance instead of changing the old one
string bar = foo.Replace('o', 'a');
string baz = foo + "bar"; // ditto here
不可变对象具有一些不错的属性,例如它们可以跨线程使用而不用担心同步问题,或者您可以直接分发私有支持字段,而不必担心有人更改了不应该更改的对象(请参阅数组或可变列表,如果不需要,通常需要在返回之前复制它们。但是当不小心使用时,它们可能会产生严重的性能问题(几乎任何事情 - 如果您需要一个以执行速度为傲的语言的示例,那么请查看C的字符串操作函数)。
如果你需要一个 mutable 字符串,例如你要逐步构建的字符串或者你改变很多东西的字符串,那么你需要一个StringBuilder
这是一个缓冲区可以更改的字符数。这在很大程度上影响了性能。如果你想要一个可变的字符串而不是普通的string
实例,那么你最终会不必要地创建和销毁大量的对象,而StringBuilder
实例本身会发生变化,从而无需对于许多新物体。
简单的例子:以下将使许多程序员痛苦地畏缩:
string s = string.Empty;
for (i = 0; i < 1000; i++) {
s += i.ToString() + " ";
}
你最终会在这里创建2001字符串,其中2000条被丢弃。使用StringBuilder的相同示例:
StringBuilder sb = new StringBuilder();
for (i = 0; i < 1000; i++) {
sb.Append(i);
sb.Append(' ');
}
这应该减少对内存分配器的压力: - )
但是应该注意,C#编译器在字符串方面相当聪明。例如,以下行
string foo = "abc" + "def" + "efg" + "hij";
将由编译器加入,在运行时只留下一个字符串。同样,诸如
之类的行string foo = a + b + c + d + e + f;
将被重写为
string foo = string.Concat(a, b, c, d, e, f);
所以你不必支付五个荒谬的连接,这是处理它的天真方式。这不会像上面那样将你保存在循环中(除非编译器展开循环,但我认为只有JIT可能实际上这样做,最好不要赌它)。
答案 1 :(得分:6)
字符串是不可变的,这意味着当您创建字符串时,您永远无法更改它。相反,它会创建一个新的字符串来存储新值,如果你需要经常更改字符串变量的值,这可能是低效的。
StringBuilder可用于模拟可变字符串,因此在需要更改字符串时很有用。
答案 2 :(得分:6)
字符串
当值发生连续变化时,性能会下降
主题安全
StringBuilder(可变字符串)
有关使用ObjectIDGenerator的大量示例的关于此主题的描述性文章,请关注this link。
相关堆栈溢出问题: Mutability of string when string doesn't change in C#
答案 3 :(得分:3)
<强>字符串强>
String实例是不可变的,也就是说,我们无法在创建它之后对其进行更改。如果我们对String执行任何操作,它将返回一个新实例(在内存中创建一个新实例),而不是修改现有实例值。
<强>的StringBuilder 强>
StringBuilder是可变的,也就是说,如果我们对StringBuilder执行任何操作,它将更新现有的实例值,并且不会创建新的实例。
答案 4 :(得分:2)
当您需要在多个步骤中构建字符串时,StringBuilder将为您提供帮助。
而不是这样做:
String x = "";
x += "first ";
x += "second ";
x += "third ";
你做了
StringBuilder sb = new StringBuilder("");
sb.Append("first ");
sb.Append("second ");
sb.Append("third");
String x = sb.ToString();
最终效果相同,但StringBuilder将使用更少的内存并且运行速度更快。它不是创建一个两个串联的新字符串,而是分别创建块,并且只在最后它将它们联合起来。
答案 5 :(得分:2)
来自StringBuilder Class documentation:
String对象是不可变的。每次使用System.String类中的某个方法时,都会在内存中创建一个新的字符串对象,这需要为该新对象分配新的空间。在需要对字符串执行重复修改的情况下,与创建新String对象相关的开销可能很昂贵。如果要在不创建新对象的情况下修改字符串,可以使用System.Text.StringBuilder类。例如,使用StringBuilder类可以在循环中将多个字符串连接在一起时提高性能。
答案 6 :(得分:1)
主要区别:
字符串是不可变的。这意味着你根本无法修改字符串;修改的结果是一个新的字符串。如果您计划附加到字符串,则无效。
StringBuilder是可变的。它可以以任何方式进行修改,并且不需要创建新实例。完成工作后,可以调用ToString()来获取字符串。
字符串可以参与实习。这意味着具有相同内容的字符串可能具有相同的地址。 StringBuilder无法实现。
String是唯一可以具有引用文字的类。
答案 7 :(得分:1)
字符串是不可变的,即如果更改它们的值,旧值将被丢弃并在堆上创建新值,而在字符串构建器中,我们可以修改现有值而不创建新值。
因此,性能方面的String Builder非常有用,因为我们不必占用更多的内存空间。
答案 8 :(得分:0)
String是一种不可变类型。这意味着每当你开始相互串联字符串时,每次都会创建新的字符串。如果你多次这样做,最终会导致很多堆开销和内存不足的风险。
StringBuilder实例用于将字符串附加到同一个实例,在您调用ToString方法时创建一个字符串。
由于实例化StringBuilder对象的开销,微软表示当你有超过5-10个字符串连接时使用它是有用的。
有关示例代码,建议您查看一下:
答案 9 :(得分:0)
String(System.String)是.NET框架内定义的类型。 String类不可变。这意味着每次对System.String实例执行操作时,.NET编译器都会创建该字符串的新实例。此操作对开发人员隐藏。
System.Text.StringBuilder是表示可变字符串的类。此类提供了一些有用的方法,使用户能够管理StringBuilder包装的String。请注意,所有操作都是在同一个StringBuilder实例上进行的。
Microsoft鼓励使用StringBuilder,因为它在内存使用方面更有效。
答案 10 :(得分:0)
String的连接的复杂性也是O(N2),而对于StringBuffer,它是O(N)。
因此,我们在循环中使用连接可能存在性能问题,因为每次都会创建许多新对象。
答案 11 :(得分:0)
如果要与字符串构建器一起遍历字符串,可以使用Clone
方法...它返回一个对象,以便您可以使用ToString方法转换为字符串......:)
答案 12 :(得分:0)
System.String是一个可变对象,意味着它在创建后无法修改。有关更好的理解,请参阅 Difference between string and StringBuilder in C#? 。