string
和StringBuilder
有什么区别?
另外,理解的例子是什么?
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可能实际上这样做而且最好不要赌它)。
String的连接的复杂性也是O(N2),而对于StringBuffer,它是O(N)。
因此,我们在循环中使用连接可能存在性能问题,因为每次都会创建许多新对象。
你可以使用Clone
方法,如果你想与字符串生成器一起遍历字符串...它返回一个对象,所以你可以使用ToString方法转换为字符串...... :)
System.String是一个可变对象,意味着它在创建后无法修改。请参阅Difference between string and StringBuilder in C#?以获得更好的理解。
String是不可变类型。这意味着每当你开始相互串联字符串时,每次都会创建新的字符串。如果这样做很多次,最终会导致很多堆开销和内存不足的风险。
StringBuilder实例用于将字符串附加到同一实例,在您调用ToString方法时创建字符串。
由于实例化StringBuilder对象的开销,微软表示当你有超过5-10个字符串连接时使用它是有用的。
有关示例代码,我建议您看一下:
字符串是不可变的,这意味着当您创建字符串时,您永远无法更改它。相反,它将创建一个新的字符串来存储新值,如果您需要经常更改字符串变量的值,这可能是低效的。
StringBuilder可用于模拟可变字符串,因此在需要更改字符串时很有用。
有关使用ObjectIDGenerator的大量示例的关于此主题的描述性文章,请关注this link。
相关Stack Overflow问题:Mutability of string when string doesn't change in C#
串
String实例是不可变的,也就是说,我们无法在创建它之后对其进行更改。如果我们对String执行任何操作,它将返回一个新实例(在内存中创建一个新实例),而不是修改现有实例值。
StringBuilder的
StringBuilder是可变的,也就是说,如果我们对StringBuilder执行任何操作,它将更新现有的实例值,并且不会创建新实例。
来自StringBuilder Class documentation:
String对象是不可变的。每次使用System.String类中的某个方法时,都会在内存中创建一个新的字符串对象,这需要为该新对象分配新的空间。在需要对字符串执行重复修改的情况下,与创建新String对象相关的开销可能很昂贵。如果要在不创建新对象的情况下修改字符串,可以使用System.Text.StringBuilder类。例如,使用StringBuilder类可以在循环中将多个字符串连接在一起时提高性能。
当您需要在多个步骤中构建字符串时,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将使用更少的内存并运行得更快。它不是创建一个两个串联的新字符串,而是分别创建块,并且只在最后它将它们联合起来。
主要区别:
字符串是不可变的。这意味着你根本无法修改字符串;修改的结果是一个新的字符串。如果您计划附加到字符串,则此方法无效。
StringBuilder是可变的。它可以以任何方式进行修改,并且不需要创建新实例。完成工作后,可以调用ToString()来获取字符串。
字符串可以参与实习。这意味着具有相同内容的字符串可能具有相同的地址。 StringBuilder无法实现。
String是唯一可以具有引用文字的类。
字符串是不可变的,即如果更改它们的值,旧值将被丢弃并在堆上创建新值,而在字符串构建器中,我们可以修改现有值而不创建新值。
因此,性能方面的String Builder是有益的,因为我们不必要地占用更多的内存空间。
String(System.String)是.NET框架内定义的类型。 String类不可变。这意味着每次对System.String实例执行操作时,.NET编译器都会创建该字符串的新实例。此操作对开发人员是隐藏的。
System.Text.StringBuilder是表示可变字符串的类。此类提供了一些有用的方法,使用户能够管理StringBuilder包装的String。请注意,所有操作都是在同一个StringBuilder实例上进行的。
Microsoft鼓励使用StringBuilder,因为它在内存使用方面更有效。