В чём разница между string и StringBuilder
string и StringBuilder — оба типа предназначены для работы с текстом, но принципиально различаются: string неизменяем (иммутабелен), а StringBuilder — изменяем. Это различие определяет их производительность и сценарии использования.
Как это работает
string в C# — это ссылочный тип, представляющий неизменяемую последовательность символов. После создания строки её содержимое изменить нельзя. Любая операция, которая выглядит как модификация (например, конкатенация через +), на самом деле создаёт новый экземпляр строки, а старая остаётся в памяти до сборки мусора.
string s = "Hello";
s += ", World!"; // Создаётся новая строка "Hello, World!", s ссылается на неёStringBuilder — это изменяемый класс, который хранит буфер символов. Он позволяет добавлять, удалять или вставлять символы, изменяя существующий буфер, без создания новых объектов на каждую операцию.
StringBuilder sb = new StringBuilder("Hello");
sb.Append(", World!"); // Добавляет текст в существующий буферПроизводительность
Из-за неизменяемости string неэффективен при частых модификациях: каждая операция создаёт новый объект, что приводит к дополнительным затратам памяти и времени. Особенно это заметно в циклах с большим числом итераций.
StringBuilder оптимизирован для многократных изменений. Он не создаёт новые объекты, а расширяет внутренний буфер, что значительно ускоряет работу и снижает нагрузку на память.
Пример сравнения:
// Неэффективно: на каждой итерации создаётся новая строка
string result = "";
for (int i = 0; i < 10000; i++) {
result += i;
}
// Эффективно: изменяется существующий буфер
StringBuilder sbResult = new StringBuilder();
for (int i = 0; i < 10000; i++) {
sbResult.Append(i);
}Когда использовать
string— когда текст не изменяется после создания: хранение констант, ключей, сообщений, передача параметров. Простота и поддержка литералов делают его удобным для неизменяемых данных.StringBuilder— когда требуется многократно изменять строку: сборка больших строк в цикле, форматирование текста, работа с логами. Он также полезен, когда заранее неизвестен итоговый размер строки.
Подводные камни
- Не используйте
StringBuilderдля простой конкатенации двух-трёх строк — накладные расходы на создание объекта не окупаются. - Помните, что
StringBuilderне переопределяетEqualsиGetHashCodeкакstring, поэтому сравнение содержимого требует вызоваToString(). - При работе с многопоточностью
StringBuilderне потокобезопасен, в отличие от неизменяемых строк.
Коротко
stringнеизменяем: каждая модификация создаёт новый объект.StringBuilderизменяем: модифицирует буфер без создания новых объектов.- Для частых изменений строк используйте
StringBuilder, для неизменяемых данных —string. - В циклах с конкатенацией
stringприводит к деградации производительности,StringBuilder— оптимален.