Строки и производительность
Вопрос
Расскажите, какие проблемы с производительностью бывают у строк в C# и как их решать.
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Неизменяемость: каждая операция создаёт новую строку
Склейка в цикле даёт O(n²), решение StringBuilder или string.Join/Concat
Лишние ToLower/ToUpper для сравнения, лучше StringComparison.OrdinalIgnoreCase
Substring и Split аллоцируют, для парсинга Span<char> и ReadOnlySpan
Интерполяция в .NET 6+ без упаковки, но строка всё равно создаётся, в логах нужны шаблоны
Интернирование и string.Intern для множества повторяющихся строк
Что могут спросить следом
- Почему
logger.LogInformation($"User {id}")хуже шаблона"User {Id}", id? - Когда имеет смысл string.Create?
Разбор
Главный источник проблем это неизменяемость: Replace, Substring, ToLower, конкатенация всегда создают новые строки. В цикле += превращается в квадратичное копирование, поэтому для неизвестного числа частей беру StringBuilder, а для коллекции string.Join.
Вторая типичная ошибка: сравнение через a.ToLower() == b.ToLower(). Это две лишние строки и зависимость от культуры. Правильно string.Equals(a, b, StringComparison.OrdinalIgnoreCase), а для словарей StringComparer.OrdinalIgnoreCase.
В горячем парсинге убираю Split и Substring, работаю с ReadOnlySpan<char>: int.Parse и IndexOf принимают span. В логах не пишу интерполяцию, а передаю шаблон с параметрами: тогда строка не собирается, если уровень логирования выключен, и структурное логирование видит поля. Если много одинаковых строк в памяти, например коды из справочника, их можно интернировать.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.