我理解String和StringBuilder之间的区别(StringBuilder是可变的),但两者之间有很大的性能差异吗?

我正在工作的程序有很多case驱动的字符串追加(500+)。使用StringBuilder是更好的选择吗?


当前回答

是的,StringBuilder在对字符串执行重复操作时提供了更好的性能。这是因为所有的更改都是对单个实例进行的,因此它可以节省大量时间,而不是像String那样创建一个新实例。

String Vs Stringbuilder

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

强烈推荐dotnet mob文章:c#中的String Vs StringBuilder。 相关堆栈溢出问题:字符串时的可变性 在c#中没有改变?

其他回答

除了前面的答案,当我想到这样的问题时,我总是做的第一件事是创建一个小型测试应用程序。在这个应用程序中,为这两种情况执行一些计时测试,看看哪个更快。

恕我直言,添加500+字符串条目绝对应该使用StringBuilder。

这个基准测试表明,当组合3个或更少字符串时,常规连接更快。

http://www.chinhdo.com/20070224/stringbuilder-is-not-always-faster/

StringBuilder可以在内存使用方面做出非常显著的改进,特别是在将500个字符串加在一起的情况下。

考虑下面的例子:

string buffer = "The numbers are: ";
for( int i = 0; i < 5; i++)
{
    buffer += i.ToString();
}
return buffer;

内存中发生了什么?创建以下字符串:

1 - "The numbers are: "
2 - "0"
3 - "The numbers are: 0"
4 - "1"
5 - "The numbers are: 01"
6 - "2"
7 - "The numbers are: 012"
8 - "3"
9 - "The numbers are: 0123"
10 - "4"
11 - "The numbers are: 01234"
12 - "5"
13 - "The numbers are: 012345"

通过将这5个数字加到字符串的末尾,我们创建了13个字符串对象!其中12个是无用的!哇!

StringBuilder fixes this problem. It is not a "mutable string" as we often hear (all strings in .NET are immutable). It works by keeping an internal buffer, an array of char. Calling Append() or AppendLine() adds the string to the empty space at the end of the char array; if the array is too small, it creates a new, larger array, and copies the buffer there. So in the example above, StringBuilder might only need a single array to contain all 5 additions to the string-- depending on the size of its buffer. You can tell StringBuilder how big its buffer should be in the constructor.

字符串Vs字符串生成器:

你要知道的第一件事是这两个类生活在哪个汇编中?

So,

字符串出现在系统命名空间中。

and

StringBuilder出现在系统中。文本名称空间。

对于字符串声明:

您必须包括System名称空间。 就像这样。 使用系统;

and

对于StringBuilder声明:

你必须包括系统。文本名称空间。 就像这样。 使用text;

现在真正的问题来了。

string和StringBuilder之间的区别是什么?

两者的主要区别在于:

字符串是不可变的。

and

StringBuilder是可变的。

现在让我们讨论一下immutable和mutable的区别

Mutable::意思是可变的。

Immutable::表示不可更改。

例如:

using System;

namespace StringVsStrigBuilder
{
    class Program
    {
        static void Main(string[] args)
        {
            // String Example

            string name = "Rehan";
            name = name + "Shah";
            name = name + "RS";
            name = name + "---";
            name = name + "I love to write programs.";

            // Now when I run this program this output will be look like this.
            // output : "Rehan Shah RS --- I love to write programs."
        }
    }
}

在这种情况下,我们要将同一个对象改变5次。

所以显而易见的问题是!当我们修改同一个字符串5次时,实际上发生了什么。

这就是当我们改变同一个字符串5次时发生的情况。

让我们看一下图表。

解释:

当我们第一次将变量name初始化为Rehan时i-e string name = "Rehan" 这个变量被创建在堆栈“name”上,并指向“Rehan”值。 "name = name + "Shah"。引用变量不再指向对象“Rehan”,而是指向“Shah”,以此类推。

string是不可变的意思是一旦我们在内存中创建了对象我们就不能改变它们。

因此,当我们连接name变量时,前一个对象仍然在内存中,另一个新的字符串对象被创建。

所以从上图中我们有五件物品,四件物品被扔掉了,它们根本不用。它们仍然保留在内存中,并占据一定的内存容量。 “垃圾回收器”负责清理内存中的资源。

在字符串的情况下,当我们反复操作字符串时我们有很多对象被创建并留在内存中。

这就是字符串变量的故事。

现在让我们看看StringBuilder对象。 例如:

using System;
using System.Text;

namespace StringVsStrigBuilder
{
    class Program
    {
        static void Main(string[] args)
        {
            // StringBuilder Example

            StringBuilder name = new StringBuilder();
            name.Append("Rehan");
            name.Append("Shah");
            name.Append("RS");
            name.Append("---");
            name.Append("I love to write programs.");


            // Now when I run this program this output will be look like this.
            // output : "Rehan Shah Rs --- I love to write programs."
        }
    }
}

在这种情况下,我们要将同一个对象改变5次。

所以显而易见的问题是!当我们修改同一个StringBuilder 5次时,实际上发生了什么。

这就是当我们修改同一个StringBuilder 5次时所发生的情况。

让我们看一下图表。

解释: 对于StringBuilder对象。你不会得到新对象。同一个对象会在内存中发生变化,所以即使你改变对象10000次,我们仍然只有一个stringBuilder对象。

你没有很多垃圾对象或非_referenced stringBuilder对象,因为它可以被更改。它是可变的意思是它会随着时间变化?

差异:

字符串存在于系统命名空间中,其中Stringbuilder存在 在系统。文本名称空间。 string是不可变的,而StringBuilder是可变的。

我的方法一直是在连接4个或更多字符串时使用StringBuilder 或 当我不知道有多少串联会发生。

好的性能相关文章在这里

StringBuilder减少了分配和赋值的数量,代价是使用了额外的内存。如果使用得当,它可以完全消除编译器需要一遍又一遍地分配越来越大的字符串,直到找到结果为止。

string result = "";
for(int i = 0; i != N; ++i)
{
   result = result + i.ToString();   // allocates a new string, then assigns it to result, which gets repeated N times
}

vs.

String result;
StringBuilder sb = new StringBuilder(10000);   // create a buffer of 10k
for(int i = 0; i != N; ++i)
{
   sb.Append(i.ToString());          // fill the buffer, resizing if it overflows the buffer
}

result = sb.ToString();   // assigns once