Строки в c#. String \ StringBuilder

100
05 января 2022, 15:00

Ребят, у меня возникли вопросы по строкам в c#.

  1. Чем отличается класс String от StringBuilder?
  2. Зачем нужно такое разделение?
  3. В чем преимущества того и другого?
  4. Что из этого лучше использовать?
  5. Почему StringBuilder лучше использовать для работы с большими объемами текста?

По возможности ответьте с примерами. Заранее спасибо за ответ.

Answer 1

String - это строки. Они неизменяемые т.е. конкретную строку нельзя подправить/дописать/укоротить. Любые операции над строками приводят к созданию новой строки (с копированием всего текста). При этом старая строка уходит в мусор (если у вас не остается на нее ссылки).

Так сделано из соображений

  • Экономии памяти - не надо подстраховываться и копировать строку "на всякий случай" при передаче куда-то в другой метод. Он ее точно никак не испортит.
  • Производительности - можно высчитывать хэш строки один раз, и не заморачиваться с поддержанием его актуальности. Это дает быстрые сравнения строк на равенство (особенно если строки разные).
  • Безопасности - код может спокойно работать с пришедшими извне строками, не опасаясь что кто-то влезет в строку по дороге.
  • Простоты работы с несколькими потоками - нет проблемы одновременных изменений.

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

Для решения этой проблемы есть класс StringBuilder. Это не "строка", а класс для сборки строк из кусков, позволяющий в конце получить результирующую строку вызовом StringBuilder.ToString().

  • Если вам надо просто работать со строками - используете String
  • Если вам надо собрать одну большую строку из пачки маленьких - используете StringBuilder
Answer 2
  1. String не изменяемый тип. То есть если Вы создадите строку потом добавите ей несколько символов то это будет не старая модифицированная строка, а в памяти аллоцируется новый объект System.String, который будет содержать в себе новую строку. При этом старый объект продолжает существовать в куче пока не произойдет сборка мусора. Такой вот безобидный код:

    string str = string.Empty;
    for(int i = 0; i < 1000; ++i)
    {
        str += "a";
    }
    

Создаст в памяти 1000 потенциальных кандидатов для GC.

При вызове метода например Append объекта StringBuilder будет изменятся уже существующая область памяти.

  1. Что бы не загружать GC лишними операциями.
  2. Преимущества очевидны -- Если у вас одна строка (например константа) то типа System.String вполне достаточно. Если же вы заранее знаете что будете много изменять строку то класс StringBuilder упростить жизнь GC и CLR. Врятли это как то скажется на производительности, если у Вас не большая система и реально вы не почувствуете разницу. Но когда в проекте идет работа с миллионами строк то тогда StringBuilder не заменим (если конечно же Вы не напишете свой механизм работы со строками на неуправляемом коде или в unsafe-коде).

Ответы на остальные вопросы очевидны.

Эта тема очень детально описана в книге "CRL via C#" Джеффри Рихтера.

READ ALSO
Dependency Injection создает экземпляры разных типов

Dependency Injection создает экземпляры разных типов

У меня есть сервис по работе с JWT

97
DataGridView извлечение информации

DataGridView извлечение информации

Курил форумы и встал вопрос :

107
Ожидание ввода текста без остановки программы

Ожидание ввода текста без остановки программы

В моей программе есть вкладка, где я могу написать и запустить кодПри его запуске, появляется окошко с двумя TextBox'ами, в первом вывод, а во втором...

72
Поможете дописать авто-редирект при успешной оплате?

Поможете дописать авто-редирект при успешной оплате?

В данный момент при любом статусе оплаты или ее стадии осуществляется редирект на нужную страницу и все ок, но только при клике на "вернуться...

190