Как правильно использовать StringBuilder

Я немного запутался в использовании classа StringBuilder , сначала:

Операция конкатенации string объекта всегда создает новый объект из существующей string и новых данных. Объект StringBuilder поддерживает буфер для размещения конкатенации новых данных. Новые данные добавляются в конец буфера, если комната доступна; в противном случае выделяется новый, более крупный буфер, данные из исходного буфера копируются в новый буфер, а затем новые данные добавляются в новый буфер.

Но где смысл создания экземпляра StringBuilder чтобы избежать создания новой String ? Это звучит как торговля «один на один».

 static void Main(string[] args) { String foo = "123"; using (StringBuilder sb = new StringBuilder(foo)) // also sb isn't disposable, so there will be error { sb.Append("456"); foo = sb.ToString(); } Console.WriteLine(foo); Console.ReadKey(); } 

Почему я не должен просто использовать

 += 

Изменить: Хорошо, теперь я знаю, как повторно использовать один экземпляр StringBuilder (до сих пор не знаю, правильно ли это относится к стандартам кода), но это не стоит использовать только с одной string , не так ли?

Изменение неизменяемых структур, таких как string s, должно выполняться путем копирования структуры и тем самым потреблять больше памяти и замедлять время выполнения приложения (также увеличивая время GC и т. Д.).

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

Однако:

при конкатенации string во время компиляции следующим образом:

 string myString = "123"; myString += "234"; myString += "345"; 

он действительно скомпилирует что-то вроде этого:

 string myString = string.Concat("123", "234", "345"); 

эта функция работает быстрее, чем работа с StringBuilder для того, чтобы количество string входящих в функцию, было известно.

поэтому для компиляции с известными string конкатенациями вы должны предпочесть string.Concat() .

как и для неизвестного числа string например, в следующем случае:

 string myString = "123"; if (Console.ReadLine() == "a") { myString += "234"; } myString += "345"; 

Теперь компилятор не может использовать string.Concat() , однако StringBuilder , по-видимому, более эффективен во времени и потреблении памяти только тогда, когда конкатенация выполняется с 6-7 или более strings .

Плохое использование практики:

 StringBuilder myString = new StringBuilder("123"); myString.Append("234"); myString.Append("345"); 

Использование тонкой практики (обратите внимание, что if используется):

 StringBuilder myString = new StringBuilder("123"); if (Console.ReadLine() == "a") { myString.Append("234"); } myString.Append("345"); 

Использование лучшей практики (обратите внимание, что в while цикл используется):

 StringBuilder myString = new StringBuilder("123"); while (Console.ReadLine() == "a") { myString.Append("234"); //Average loop times 4~ or more } myString.Append("345"); 

stringнеизменный class . Вы не можете его изменить, только создайте новые strings .

Поэтому, когда вы пишете result += a; в этой точке у вас есть три отдельные strings : a , старое значение result и новое значение. Конечно, это абсолютно нормально, если вы только конкатенируете ограниченное количество strings . Если вы делаете это в цикле for итерации по большой коллекции, это может стать проблемой.

Класс StringBuilder обеспечивает повышенную производительность в этих случаях. Вместо того, чтобы создавать новые strings для хранения результата конкатенации, он использует один и тот же объект. Поэтому, если вы используете stringBuilder.Append(a); у вас никогда не будет эквивалента «старого значения result ».


Разумеется, эффективность этой памяти идет с ценой. Когда только конкатенирование небольшого числа strings StringBuilder часто менее эффективен в отношении скорости, поскольку у него больше накладных расходов по сравнению с неизменным classом string .


Следует иметь в виду, что если вам нужны промежуточные строки, то StringBuilder может стать менее эффективным, так как вызов .ToString() на нем создает новую копию string .

Причина в том, что strings неизменяемы. При конкатенации string вы создаете новую string . Итак, когда вам нужно объединить много strings вы создаете много objects . Это не так дорого в плане памяти, поскольку каждая string используется один раз. Но это дает дополнительную работу для GC .

Однако StringBuilder использует один и тот же object каждый раз, но он делает это за счет простоты использования.

  • Почему StringBuilder, когда есть String?
  • Давайте будем гением компьютера.