1. Введение
Напомню, строки в C# — неизменяемы (immutable). Это значит, что после создания строку нельзя изменить: любые операции, которые вроде как "меняют" строку, на самом деле создают новую строку в памяти.
Например, когда вы пишете:
string hello = "Привет";
hello += " мир!"; // Кажется, hello изменилась, но на самом деле создан новый объект!
Переменная hello указывает на новый объект, а старый (если нигде не используется) однажды удалит сборщик мусора. Если вы выполняете подобные действия в цикле много раз, может возникнуть "завал" в оперативной памяти и резкое падение производительности. Это особенно ощутимо, если объединяете тысячи или миллионы строк: в каждом шаге создается новая строка, копируются все её символы, старые объекты висят до сбора мусора, а ваша программа вдруг начинает тормозить.
Вот тут на сцену выходит герой этой лекции — StringBuilder.
using System.Text; // ← обязательно!
StringBuilder sb = new StringBuilder("Привет");
sb.Append(" мир!"); // Теперь строка меняется быстро и эффективно<
Знакомство со StringBuilder
StringBuilder — это класс из пространства имён System.Text. Его задача — эффективно создавать и собирать большие строки, изменяя их содержимое без постоянного создания новых объектов.
Аналогия:
Если строка (string) — это кусочек мозаики, который можно только полностью заменить, то StringBuilder — это магнитная доска, на которую можно бесконечно “лепить” и убирать эти кусочки, не заводя новую доску каждый раз, когда нужно добавить или убрать кусочки мозаики.
Когда стоит использовать StringBuilder?
- Если вы изменяете строку много раз (особенно в цикле).
- Если собираете текст из большого количества маленьких кусочков.
- Если вас волнует скорость и использование памяти.
Когда НЕ стоит использовать?
- Если у вас всего 1-2 простых операций со строкой ― обычный string проще и читаемее.
- Если вы реально хотите (зачем-то) сохранить каждое отдельное состояние строки.
2. Создание и базовые операции с StringBuilder
Подключение пространства имён
Начать работу просто: не забудьте подключить пространство имён.
using System.Text;// ← обязательно!
Способы создания новой строки
StringBuilder sb1 = new StringBuilder(); // Пустой
StringBuilder sb2 = new StringBuilder("Старт"); // С начальным текстом
StringBuilder sb3 = new StringBuilder(100); // С запасом под 100 символов
Основные методы
var sb = new StringBuilder("Начало");
sb.Append(" + добавили новый текст"); // Добавить в конец
sb.AppendLine(" (а это с переводом строки)"); // Добавить с \n
sb.Insert(0, "Старт: "); // Вставить с позиции 0
sb.Remove(0, 7); // Удалить 7 символов с позиции 0
sb.Replace("текст", "STRING"); // Заменить все "текст" на "STRING"
string result = sb.ToString(); // Получить итоговую строку
3. Эффективность StringBuilder
Пример: сравнение производительности
Пусть надо собрать строку из 10 000 чисел подряд (а вдруг вам поручили вывести все номера своих одногруппников):
Наивный подход (string)
string text = "";
for (int i = 0; i < 10000; i++)
{
text += i + " "; // На каждом шаге создается новая строка!
}
Console.WriteLine(text.Substring(0, 100) + "..."); // Для краткости вывода
Оптимальный подход (StringBuilder)
var sb = new StringBuilder();
for (int i = 0; i < 10000; i++)
{
sb.Append(i).Append(' '); // Можно цепочкой!
}
Console.WriteLine(sb.ToString().Substring(0, 100) + "...");
В чём разница?
Первый вариант будет работать ощутимо медленнее и может “съесть” гораздо больше памяти. Второй — быстрый и не требовательный к оперативке.
4. Самые популярные методы StringBuilder
Append — добавляет строку или другой тип (автоматически преобразует к строке):
sb.Append("текст");
sb.Append(123); // 123 превратится в "123"
sb.Append('!'); // Символ
AppendLine — добавляет строку + символ новой строки:
sb.AppendLine("строка"); // Добавит "строка\n"
Insert — вставляет строку на определённую позицию:
sb.Insert(0, "Hello, "); // Вставка в начало
Remove — удаляет несколько символов:
sb.Remove(3, 4); // Удаляет 4 символа начиная с позиции 3
Replace — заменяет все вхождения подстроки или символа:
sb.Replace("old", "new");
sb.Replace('a', 'A');
ToString — возвращает готовую строку.
Обрезка строки
В отличии от string, объекту типа StringBuilder можно присвоить новое значение длины. При этом строка обрежется до нее.
sb.Length = 10; // Всё, что после 10 символа — исчезает!
5. Особенности работы и типичные ошибки
Почему ToString() важен
Пока вы работаете с StringBuilder, у вас "в руках" не строка, а специальный объект. Многие методы (например, Console.WriteLine) спокойно принимают и его, потому что он умеет автоматически превращаться в строку, но иногда вас может ожидать сюрприз — если вы случайно сравниваете с обычной строкой или делаете что-то вроде:
if (sb == "Привет") { ... } // Ой! Это не сработает, даже если sb содержит "Привет"
Результат будет false: сравниваются не строки, а объекты разных типов.
Верно:
if (sb.ToString() == "Привет") { ... }
Мутируемость
В отличие от string, StringBuilder — изменяемый (mutable)! Один объект может менять содержимое сколько угодно раз, что и даёт выигрыш по скорости.
Не забывайте про ToString() в финале работы с объектом, иначе вы получите не строку, а загадочный текст вида System.Text.StringBuilder.
Размер буфера и его перераспределение
Внутри себя StringBuilder хранит массив символов. Если вы заранее знаете, что собираетесь "намутить" очень длинную строку, можно передать в конструктор предполагаемую длину — это слегка ускорит работу.
var bigBuilder = new StringBuilder(50000); // Ожидаем 50 тысяч символов
Но если вы ошиблись — не беда! StringBuilder при необходимости расширит буфер сам, просто это будет чуть медленнее.
Переполнение памяти?
Теоретически, если вы вообще не знаете меры и добавляете миллиарды символов, можно "долезть" до OutOfMemoryException, но для реальных задач это почти никогда не случается.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ