字符串连接是否为链中的每个字符串在内存中分配新字符串,还是仅为要更改的字符串分配新字符串?

时间:2011-08-18 17:51:16

标签: c# string stringbuilder

//will need these in a second
string a = "5";
string b = "7";
string c = "3";

因为C#会在内存中分配更多的字符串

string mystring = "";
mystring += a;
mystring += b;
mystring += c;

会慢于

StringBuilder sb = new StringBuilder();
sb.Append(a).Append(b).Append(c);

那么,那么:

string mystring = "";
mystring += a + b + c;

只是+=部分是慢的,还是+也是罪魁祸首?

6 个答案:

答案 0 :(得分:6)

这一行:

mystring += "5" + "7" + "3";

实际上会编译为:

mystring = String.Concat(mystring, "573");

当您连接文字字符串时,编译器将在编译时为您执行此操作。

如果您改为使用字符串变量:

string mystring = "";
string str1 = "5";
string str2 = "7";
string str3 = "3";
mystring += str1 + str2 + str3;

最后一行将编译为:

mystring = String.Concat(myString, str1, str2, str3);

当您将所有字符串发送到Concat方法时,它可以一次创建结果字符串。它的作用与使用StringBuilder创建字符串非常相似。

答案 1 :(得分:0)

+ =是s + a的语法糖。

性能如何,对于大量的字符串,StringBuilder的性能要高得多。

答案 2 :(得分:0)

没有区别。字符串连接是我认为的字符串连接。如果你只进行几个连接(3或4),最好不要使用StringBuilder,因为StringBuilder的开销可能比连接慢。

更新

以下是我为验证这一点而编写的测试:

    [Test]
    public void TestString() {
        IList<string> strings = new List<string>();
        Stopwatch watch = new Stopwatch();
        watch.Start();
        for (int index = 0; index < 100000; index++) {
            string t = "1" + "2" + "3";
            // Keep the compiler from optimizing this away
            strings.Add(t);
        }
        watch.Stop();
        Console.WriteLine("string: " + watch.ElapsedMilliseconds);
        watch.Reset();
        watch.Start();
        for (int index = 0; index < 100000; index++) {
            StringBuilder b = new StringBuilder();
            b.Append("1").Append("2").Append("3");
            strings.Add(b.ToString());
        }
        watch.Stop();
        Console.WriteLine("StringBuilder: " + watch.ElapsedMilliseconds);
    }

产生这个输出:

string: 1
StringBuilder: 25

答案 3 :(得分:0)

我认为你的例子对变量会更好。编译器实际上会为您执行此连接,因为这是两个字符串文字。因此,在这个示例中,实际上将完成所有工作,并且不会有任何性能损失。

为了给你一个更好的答案,把它们放在同一条线上是没有好处的。编译器将以相同的方式处理它们并执行相同数量的新字符串创建,无论每个连接是否是它自己的行或它们是否被链接。

答案 4 :(得分:0)

在第一种情况下,您可以假设编译器或JIT执行追加并仅分配一个字符串。如果常量字符串被编译时未知的变量替换,StringBuilder应该更快,因为它不会分配那么多字符串。

另一方面,长度= 1的三​​个字符串不需要太多分配,并且可能比实例化StringBuilder更快。只有谨慎测量的人才能确定。

答案 5 :(得分:0)

以下将使3次内存分配多次复制数据:

string mystring = "";
mystring += a; // allocate string; copy a
mystring += b; // allocate string; copy a and b
mystring += c; // allocate string; copy a, b, and c

这可能会产生2次内存分配并将数据复制两次:

StringBuilder sb = new StringBuilder(); // make 1 allocation for all the strings
sb.Append(a).Append(b).Append(c); // copy a, b, and c
string mystring = sb.ToString();  // make another allocation; copy a, b, and c

这将只进行1次内存分配,并且只复制每个字符串一次,因为编译器将连续的字符串连接优化为对String.Concat的单个调用:

string mystring = "";
mystring += a + b + c; // allocate one string; copy a, b, and c