C#中String和StringBuilder的区别

时间:2010-06-18 12:09:48

标签: c# string stringbuilder

stringStringBuilder之间有什么区别?

此外,理解的例子是什么?

13 个答案:

答案 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)

String vs. StringBuilder

  • 字符串

    • 在系统命名空间
    • 不可变(只读)实例
    • 当值发生连续变化时,性能会下降

    • 主题安全

  • StringBuilder(可变字符串)

    1. 在System.Text名称空间
    2. 可变实例
    3. 自从对现有实例进行了新的更改后,显示出更好的性能

有关使用ObjectIDGenerator的大量示例的关于此主题的描述性文章,请关注this link

相关堆栈溢出问题: Mutability of string when string doesn't change in C#

答案 3 :(得分:3)

<强>字符串

String实例是不可变的,也就是说,我们无法在创建它之后对其进行更改。如果我们对String执行任何操作,它将返回一个新实例(在内存中创建一个新实例),而不是修改现有实例值。

<强>的StringBuilder

StringBuilder是可变的,也就是说,如果我们对StringBuilder执行任何操作,它将更新现有的实例值,并且不会创建新的实例。

Difference between String and 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#?