Распределяет ли конкатенация строк новые строки в памяти для каждой строки в цепочке или только для изменяемой строки? - PullRequest
1 голос
/ 18 августа 2011
//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 ]

6 голосов
/ 18 августа 2011

Эта строка:

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 для создания строки.

0 голосов
/ 18 августа 2011

В следующем случае 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
0 голосов
/ 18 августа 2011

В первом случае вы можете предположить, что компилятор или JIT выполняют добавление и выделяют только одну строку. Если константные строки заменяются переменными, которые не известны во время компиляции, StringBuilder должен быть быстрее, поскольку он не выделяет столько строк.

С другой стороны, три строки с длиной = 1 не требуют большого выделения и могут быть быстрее, чем экземпляр StringBuilder в любом случае. Только тот, кто тщательно измеряет, будет знать наверняка.

0 голосов
/ 18 августа 2011

Ну, я думаю, ваш пример будет лучше с переменными. Компилятор фактически сделает это для вас, так как это два строковых литерала. Таким образом, в этом примере вся работа будет выполнена, а производительность не снизится.

Чтобы дать вам лучший ответ, ставить их в одну линию не имеет смысла. Компилятор будет обрабатывать их одинаково и создавать одинаковое количество новых строк независимо от того, является ли каждая конкатенация отдельной строкой или они связаны друг с другом.

0 голосов
/ 18 августа 2011

Разницы нет. Я считаю, что конкатенация строк - это конкатенация строк. Если вы выполняете только несколько конкатенаций (3 или 4), вероятно, лучше не использовать StringBuilder, поскольку у StringBuilder есть издержки, которые могут быть медленнее, чем конкатенации.

UPDATE

Вот тест, который я написал, чтобы проверить это:

    [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
0 голосов
/ 18 августа 2011

+ = - это синтаксис Sugare для s + a.

Что касается производительности, то при большом количестве строк StringBuilder гораздо более производительный.

...