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

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


当前回答

StringBuilder更适合从许多非常量值构建字符串。

If you're building up a string from a lot of constant values, such as multiple lines of values in an HTML or XML document or other chunks of text, you can get away with just appending to the same string, because almost all compilers do "constant folding", a process of reducing the parse tree when you have a bunch of constant manipulation (it's also used when you write something like int minutesPerYear = 24 * 365 * 60). And for simple cases with non-constant values appended to each other, the .NET compiler will reduce your code to something similar to what StringBuilder does.

但是当你的append不能被编译器简化为更简单的东西时,你将需要一个StringBuilder。正如fizch所指出的,这更有可能发生在循环内部。

其他回答

我已经看到,在StringBuilder的实例上使用EnsureCapacity(int capacity)方法调用,然后再将它用于任何字符串存储,可以显著提高性能。我通常在实例化后的代码行中调用它。它的效果和你这样实例化StringBuilder是一样的:

var sb = new StringBuilder(int capacity);

该调用会提前分配所需的内存,从而在多个Append()操作期间减少内存分配。您必须对需要多少内存做出有根据的猜测,但对于大多数应用程序来说,这应该不会太难。我通常会在内存过多的情况下犯错(我们说的是1k左右)。

从内存的角度来看,StringBuilder的性能会更好。至于处理,执行时间的差异可以忽略不计。

一个简单的例子来演示使用String连接和StringBuilder在速度上的差异:

System.Diagnostics.Stopwatch time = new Stopwatch();
string test = string.Empty;
time.Start();
for (int i = 0; i < 100000; i++)
{
    test += i;
}
time.Stop();
System.Console.WriteLine("Using String concatenation: " + time.ElapsedMilliseconds + " milliseconds");

结果:

使用字符串串联:15423毫秒

StringBuilder test1 = new StringBuilder();
time.Reset();
time.Start();
for (int i = 0; i < 100000; i++)
{
    test1.Append(i);
}
time.Stop();
System.Console.WriteLine("Using StringBuilder: " + time.ElapsedMilliseconds + " milliseconds");

结果:

使用StringBuilder: 10毫秒

结果,第一次迭代花费了15423毫秒,而使用StringBuilder的第二次迭代花费了10毫秒。

在我看来,使用StringBuilder更快,快得多。

字符串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是可变的。

是的,性能差异是显著的。请参阅KB文章“如何在Visual c#中提高字符串连接性能”。

我总是试着先编写清晰的代码,然后再优化性能。这比反过来做要容易得多!但是,看到了两者在我的应用程序中的巨大性能差异后,我现在更仔细地考虑了一下。

幸运的是,在代码上运行性能分析相对简单,可以看到您在哪些地方花费了时间,然后在需要的地方修改它以使用StringBuilder。