Когда использовать StringBuilder? - PullRequest
63 голосов
/ 01 декабря 2009

Я понимаю преимущества StringBuilder.

Но если я хочу объединить 2 строки, то я предполагаю, что лучше (быстрее) сделать это без StringBuilder. Это правильно?

В какой момент (количество строк) становится лучше использовать StringBuilder?

Ответы [ 12 ]

68 голосов
/ 01 декабря 2009

Я настоятельно рекомендую вам прочитать Печальная трагедия театра микрооптимизации , Джеффа Этвуда.

Он рассматривает простую конкатенацию против StringBuilder и другие методы.

Теперь, если вы хотите увидеть некоторые цифры и графики, перейдите по ссылке;)

39 голосов
/ 01 декабря 2009

Но если я хочу объединить 2 строки, тогда я предполагаю, что это лучше (быстрее) сделать это без StringBuilder. Это правильно?

Это действительно правильно, вы можете найти, почему точно объяснили очень хорошо на:

http://www.yoda.arachsys.com/csharp/stringbuilder.html

Подводя итог: если вы можете объединить строки за один раз, как

var result = a + " " + b  + " " + c + ..

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

Для структуры типа

var result = a;
result  += " ";
result  += b;
result  += " ";
result  += c;
..

новые объекты создаются каждый раз, поэтому вы должны рассмотреть StringBuilder.

В конце статьи приведены следующие практические правила:

Правила большого пальца

Итак, когда вы должны использовать StringBuilder, и когда вы должны использовать строку операторы конкатенации?

  • Определенно используйте StringBuilder, когда вы объединяете в нетривиальном петля - особенно если вы не знаете наверняка (во время компиляции) сколько итерации, которые вы будете делать через петля. Например, чтение файла характер за один раз, создавая Строка, как вы идете, используя оператор + = потенциально самоубийство производительности.

  • Определенно используйте конкатенацию оператор, когда вы можете (читаемо) указать все, что должно быть объединены в одном заявлении. (Если ты иметь множество вещей, чтобы объединить, рассмотреть вопрос о звонке String.Concat явно - или String.Join, если вам нужен разделитель.)

  • Не бойтесь разбить литералы на несколько сцепленных битов - результат будет таким же. Вы можете помочь удобочитаемость, ломая длинный литерал в несколько строк, например, с без ущерба для производительности.

  • Если вам нужны промежуточные результаты конкатенации чего-то кроме подачи следующей итерации конкатенации, StringBuilder не является собираюсь помочь вам. Например, если вы создаете полное имя из первого имя и фамилию, а затем добавить третья часть информации ( прозвище, может быть) до конца только выгода от использования StringBuilder если вам не нужно (имя + фамилия) строка для других целей (как мы делаем в примере, который создает объект Person).

  • Если у вас есть несколько объединений делать, и вы действительно хотите сделать их в отдельных заявлениях это не действительно важно, каким путем вы идете. Который Более эффективный способ будет зависеть от количество конкатенаций размеров строки и в каком порядке они соединены. Если вы действительно считаю, что кусок кода, чтобы быть узкое место, профиль или сравните это в обе стороны.

11 голосов
/ 01 декабря 2009

System.String является неизменным объектом - это означает, что всякий раз, когда вы изменяете его содержимое, он выделяет новую строку, и это занимает время (и память?) Используя StringBuilder, вы изменяете фактическое содержимое объекта без выделения нового.

Так что используйте StringBuilder, когда вам нужно сделать много изменений в строке.

8 голосов
/ 01 декабря 2009

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

4 голосов
/ 19 сентября 2016
  • Если вы объединяете строки в цикле, вам следует рассмотреть возможность использования StringBuilder вместо обычной String
  • В случае единой конкатенации вы можете вообще не видеть разницу во времени выполнения

Вот простое тестовое приложение, чтобы доказать свою правоту:

class Program
{
    static void Main(string[] args)
    {
        const int testLength = 30000;
        var StartTime = DateTime.Now;

        //TEST 1 - String
        StartTime = DateTime.Now;
        String tString = "test string";
        for (int i = 0; i < testLength; i++)
        {
            tString += i.ToString();
        }
        Console.WriteLine((DateTime.Now - StartTime).TotalMilliseconds.ToString());
        //result: 2000 ms

        //TEST 2 - StringBuilder
        StartTime = DateTime.Now;
        StringBuilder tSB = new StringBuilder("test string");
        for (int i = 0; i < testLength; i++)
        {
            tSB.Append(i.ToString());
        }
        Console.WriteLine((DateTime.Now - StartTime).TotalMilliseconds.ToString());
        //result: 4 ms

        Console.ReadLine();
    }
}

Результаты:

  • 30'000 итераций

    • Строка - 2000 мс
    • StringBuilder - 4 мс
  • 1000 итераций

    • Строка - 2 мс
    • StringBuilder - 1 мс
  • 500 итераций

    • Строка - 0 мс
    • StringBuilder - 0 мс
4 голосов
/ 01 декабря 2009

Перефразировать

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

Обычно я использую построитель строк для любого блока кода, который приводит к объединению трех или более строк.

4 голосов
/ 01 декабря 2009

Нет окончательного ответа, только эмпирические правила. Мои личные правила действуют примерно так:

  • При объединении в цикле всегда используйте StringBuilder.
  • Если строки большие, всегда используйте StringBuilder.
  • Если код сцепления аккуратный и читаемый на экране, то, вероятно, все в порядке. Если это не так, используйте StringBuilder.
4 голосов
/ 01 декабря 2009

Но если я хочу объединить 2 строки, то я предполагаю, что лучше и быстрее сделать это без StringBuilder. Это правильно?

Да. Но что еще более важно, читаемо гораздо лучше использовать ваниль String в таких ситуациях. Использование его в цикле, с другой стороны, имеет смысл и может быть таким же удобным для чтения, как и конкатенация.

Я бы с осторожностью относился к практическим правилам, в которых в качестве порогового значения приводятся конкретные числа конкатенации. Использование его в циклах (и только в циклах), вероятно, столь же полезно, легче запомнить и имеет больше смысла.

3 голосов
/ 01 декабря 2009

Пока вы можете физически набирать количество конкатенаций (a + b + c ...), это не должно иметь большого значения. N в квадрате (при N = 10) - это 100-кратное замедление, которое не должно быть слишком плохим.

Большая проблема, когда вы объединяете сотни строк. При N = 100 вы получаете замедление в 10000 раз. Что довольно плохо.

2 голосов
/ 01 декабря 2009

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

Для меня я не буду использовать StringBuilder, если просто объединю 2 огромные строки. Если есть цикл с недетерминированным счетом, я, вероятно, сделаю это, даже если цикл может быть небольшим.

...