Класс StringBuilder

Последнее обновление: 05.01.2022

Хотя класс System.String предоставляет нам широкую функциональность по работе со строками, все таки он имеет свои недостатки. Прежде всего, объект String представляет собой неизменяемую строку. Когда мы выполняем какой-нибудь метод класса String, система создает новый объект в памяти с выделением ему достаточного места. Удаление первого символа - не самая затратная операция. Однако когда подобных операций множество, а объем текста, для которого надо выполнить данные операции, также не самый маленький, то издержки при потере производительности становятся более существенными.

Чтобы выйти из этой ситуации во фреймворк .NET был добавлен новый класс StringBuilder, который находится в пространстве имен System.Text. Этот класс представляет динамическую строку.

Создание StringBuilder

Для создания объекта StringBuilder можно использовать ряд его конструкторов. Прежде всего можно создать пустой StringBuilder:

using System.Text;

StringBuilder sb = new StringBuilder();

Можно сразу инициализировать объект определенной строкой:

StringBuilder sb = new StringBuilder("Привет мир");

С помощью метода ToString() мы можем получить строку, которая хранится в StringBuilder:

var sb = new StringBuilder("Hello World");
Console.WriteLine(sb.ToString());    //  Hello World

Либо можно просто передать объект StringBuilder:

var sb = new StringBuilder("Hello World");
Console.WriteLine(sb);    //  Hello World

Длина и емкость StringBuilder

Для хранения длины строки в классе StringBuilder определенно свойство Length. Однако есть и вторая величина - емкость выделенной памяти. Это значение хранится в свойстве Capacity. Емкость - это выделенная память под объект. Установка емкости позволяет уменьшить выделения памяти и тем самым повысить производительность.

Если строка, которая передается в конструктор StringBuilder, имеет длину 16 символов или меньше, то начальная ёмкость в StringBuilder равна 16. Если начальная строка больше 16 символов, то в качестве начальной емкости StringBuilder будет использовать длину строки.

Например, посмотрим, что содержат данные свойства:

using System.Text;

StringBuilder sb = new StringBuilder("Привет мир");
Console.WriteLine($"Длина: {sb.Length}");		// Длина: 10
Console.WriteLine($"Емкость: {sb.Capacity}");	// Емкость: 16

Хотя в данном случае длина равна 10 символов, но реально емкость будет составлять по умолчанию 16 символов. То есть мы видим, что при создании строки StringBuilder выделяет памяти больше, чем необходимо этой строке. При увеличении строки в StringBuilder, когда количество символов превосходит начальную емкость, то емкость увеличивается в два и более раз.

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

var sb = new StringBuilder(32);

StringBuilder также позволяет сразу задать строку и емкость:

var sb = new StringBuilder("Привет мир", 32);

Операции со строками в StringBuilder

Для операций над строками класс StringBuilder определяет ряд методов:

  • Append: добавляет подстроку в объект StringBuilder

  • Insert: вставляет подстроку в объект StringBuilder, начиная с определенного индекса

  • Remove: удаляет определенное количество символов, начиная с определенного индекса

  • Replace: заменяет все вхождения определенного символа или подстроки на другой символ или подстроку

  • AppendFormat: добавляет подстроку в конец объекта StringBuilder

Теперь посмотрим на примере метода Append() использование и преимущества класса StringBuilder:

using System.Text;

var sb = new StringBuilder("Название: ");
Console.WriteLine(sb);   // Название: 
Console.WriteLine($"Длина: {sb.Length}"); // 10
Console.WriteLine($"Емкость: {sb.Capacity}"); // 16

sb.Append(" Руководство");
Console.WriteLine(sb);   // Название: Руководство
Console.WriteLine($"Длина: {sb.Length}"); // 22
Console.WriteLine($"Емкость: {sb.Capacity}"); // 32

sb.Append(" по C#");
Console.WriteLine(sb);   // Название: Руководство по C#
Console.WriteLine($"Длина: {sb.Length}"); // 28
Console.WriteLine($"Емкость: {sb.Capacity}"); // 32

При создании объекта StringBuilder выделяется память по умолчанию для 16 символов, так как длина начальной строки меньше 16.

Дальше применяется метод Append - этот метод добавляет к строке подстроку. Так как при объединении строк их общая длина - 22 символа - превышает начальную емкость в 16 символов, то начальная емкость удваивается - до 32 символов.

Если бы итоговая длина строки была бы больше 32 символов, то емкость расширялась бы до размера длины строки.

Далее опять применяется метод Append, однако финальная длина уже будет 28 символов, что меньше 32 символов, и дополнительная память не будет выделяться.

Используем остальные методы StringBuilder:

var sb = new StringBuilder("Привет мир");
sb.Append("!");
sb.Insert(7, "компьютерный ");
Console.WriteLine(sb);	// Привет компьютерный мир!

// заменяем слово
sb.Replace("мир", "world");
Console.WriteLine(sb);	// Привет компьютерный world!

// удаляем 13 символов, начиная с 7-го
sb.Remove(7, 13);
Console.WriteLine(sb);	// Привет world!

// получаем строку из объекта StringBuilder
string text = sb.ToString();
Console.WriteLine(text);	// Привет world!

Когда надо использовать класс String, а когда StringBuilder?

Microsoft рекомендует использовать класс String в следующих случаях:

  • При небольшом количестве операций и изменений над строками

  • При выполнении фиксированного количества операций объединения. В этом случае компилятор может объединить все операции объединения в одну

  • Когда надо выполнять масштабные операции поиска при построении строки, например IndexOf или StartsWith. Класс StringBuilder не имеет подобных методов.

Класс StringBuilder рекомендуется использовать в следующих случаях:

  • При неизвестном количестве операций и изменений над строками во время выполнения программы

  • Когда предполагается, что приложению придется сделать множество подобных операций

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850