C#中String和StringBuilder的区别

问题描述 投票:68回答:13

stringStringBuilder有什么区别?

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

c# string stringbuilder
13个回答
97
投票

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的字符串操作函数)。

当你需要一个可变的字符串,例如你正在逐步构建的字符串或你改变很多东西的字符串时,你需要一个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可能实际上这样做而且最好不要赌它)。


0
投票

String的连接的复杂性也是O(N2),而对于StringBuffer,它是O(N)。

因此,我们在循环中使用连接可能存在性能问题,因为每次都会创建许多新对象。


0
投票

你可以使用Clone方法,如果你想与字符串生成器一起遍历字符串...它返回一个对象,所以你可以使用ToString方法转换为字符串...... :)


0
投票

System.String是一个可变对象,意味着它在创建后无法修改。请参阅Difference between string and StringBuilder in C#?以获得更好的理解。


0
投票

String是不可变类型。这意味着每当你开始相互串联字符串时,每次都会创建新的字符串。如果这样做很多次,最终会导致很多堆开销和内存不足的风险。

StringBuilder实例用于将字符串附加到同一实例,在您调用ToString方法时创建字符串。

由于实例化StringBuilder对象的开销,微软表示当你有超过5-10个字符串连接时使用它是有用的。

有关示例代码,我建议您看一下:


6
投票

字符串是不可变的,这意味着当您创建字符串时,您永远无法更改它。相反,它将创建一个新的字符串来存储新值,如果您需要经常更改字符串变量的值,这可能是低效的。

StringBuilder可用于模拟可变字符串,因此在需要更改字符串时很有用。


6
投票

String vs. StringBuilder

  • 串 在系统名称空间下 不可变(只读)实例 当值发生连续变化时,性能会下降 线程安全
  • StringBuilder(可变字符串) 在System.Text命名空间下 可变实例 显示更好的性能,因为对现有实例进行了新的更改

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

相关Stack Overflow问题:Mutability of string when string doesn't change in C#


3
投票

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

StringBuilder的

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

Difference between String and StringBuilder


2
投票

来自StringBuilder Class documentation

String对象是不可变的。每次使用System.String类中的某个方法时,都会在内存中创建一个新的字符串对象,这需要为该新对象分配新的空间。在需要对字符串执行重复修改的情况下,与创建新String对象相关的开销可能很昂贵。如果要在不创建新对象的情况下修改字符串,可以使用System.Text.StringBuilder类。例如,使用StringBuilder类可以在循环中将多个字符串连接在一起时提高性能。


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将使用更少的内存并运行得更快。它不是创建一个两个串联的新字符串,而是分别创建块,并且只在最后它将它们联合起来。


1
投票

主要区别:

字符串是不可变的。这意味着你根本无法修改字符串;修改的结果是一个新的字符串。如果您计划附加到字符串,则此方法无效。

StringBuilder是可变的。它可以以任何方式进行修改,并且不需要创建新实例。完成工作后,可以调用ToString()来获取字符串。

字符串可以参与实习。这意味着具有相同内容的字符串可能具有相同的地址。 StringBuilder无法实现。

String是唯一可以具有引用文字的类。


1
投票

字符串是不可变的,即如果更改它们的值,旧值将被丢弃并在堆上创建新值,而在字符串构建器中,我们可以修改现有值而不创建新值。

因此,性能方面的String Builder是有益的,因为我们不必要地占用更多的内存空间。


0
投票

String(System.String)是.NET框架内定义的类型。 String类不可变。这意味着每次对System.String实例执行操作时,.NET编译器都会创建该字符串的新实例。此操作对开发人员是隐藏的。

System.Text.StringBuilder是表示可变字符串的类。此类提供了一些有用的方法,使用户能够管理StringBuilder包装的String。请注意,所有操作都是在同一个StringBuilder实例上进行的。

Microsoft鼓励使用StringBuilder,因为它在内存使用方面更有效。

© www.soinside.com 2019 - 2024. All rights reserved.