Встречается на 44% собеседований по C#

В чём разница между string и StringBuilder

string и StringBuilder — оба типа предназначены для работы с текстом, но принципиально различаются: string неизменяем (иммутабелен), а StringBuilder — изменяем. Это различие определяет их производительность и сценарии использования.

Как это работает

string в C# — это ссылочный тип, представляющий неизменяемую последовательность символов. После создания строки её содержимое изменить нельзя. Любая операция, которая выглядит как модификация (например, конкатенация через +), на самом деле создаёт новый экземпляр строки, а старая остаётся в памяти до сборки мусора.

csharp
string s = "Hello";
s += ", World!"; // Создаётся новая строка "Hello, World!", s ссылается на неё

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

csharp
StringBuilder sb = new StringBuilder("Hello");
sb.Append(", World!"); // Добавляет текст в существующий буфер

Производительность

Из-за неизменяемости string неэффективен при частых модификациях: каждая операция создаёт новый объект, что приводит к дополнительным затратам памяти и времени. Особенно это заметно в циклах с большим числом итераций.

StringBuilder оптимизирован для многократных изменений. Он не создаёт новые объекты, а расширяет внутренний буфер, что значительно ускоряет работу и снижает нагрузку на память.

Пример сравнения:

csharp
// Неэффективно: на каждой итерации создаётся новая строка
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 — оптимален.
как отвечать на вопрос
пример собеседования
фреймворки на собеседовании
типичные вопросы junior
интервью вопросы и ответы