Какие особенности строк в C#?

«Какие особенности строк в C#?» — вопрос из категории C# Core, который задают на 28% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Строки в C# — это неизменяемые (immutable) последовательности символов Unicode, представленные типом System.String. Их ключевые особенности:

1. Неизменяемость (Immutability) При любой модификации создаётся новый объект строки. Это обеспечивает потокобезопасность и безопасность, но требует аккуратной работы с производительностью.

string original = "Hello";
string modified = original + " World"; // Создаётся новая строка, "Hello" остаётся в памяти
Console.WriteLine(object.ReferenceEquals(original, modified)); // False

2. Интернирование строк (String Interning) CLR хранит литералы в пуле строк (intern pool), что позволяет повторно использовать одинаковые строковые литералы для экономии памяти.

string a = "test";
string b = "test";
string c = new StringBuilder().Append("te").Append("st").ToString();
Console.WriteLine(object.ReferenceEquals(a, b)); // True (интернирование)
Console.WriteLine(object.ReferenceEquals(a, c)); // False (не интернирована)
Console.WriteLine(string.IsInterned(c) != null); // Можно принудительно интернировать

3. Оптимизация конкатенации Для множественных операций конкатенации всегда используйте StringBuilder вместо оператора + или string.Concat() в цикле.

// Плохо: создаёт промежуточные строки O(n²)
string result = "";
for (int i = 0; i < 100; i++) result += i;

// Хорошо: эффективное построение
var sb = new StringBuilder();
for (int i = 0; i < 100; i++) sb.Append(i);
string result = sb.ToString();

4. Форматирование Используйте интерполяцию строк ($"Value: {value}") вместо string.Format() для лучшей читаемости и производительности (компилятор оптимизирует в string.Format).

5. Юникод и суррогатные пары Один символ (char) может занимать 2 байта (UTF-16), а для символов за пределами Basic Multilingual Plane (например, эмодзи) требуется суррогатная пара — два char.

string emoji = "😀";
Console.WriteLine(emoji.Length); // 2 (суррогатная пара)
Console.WriteLine(new StringInfo(emoji).LengthInTextElements); // 1 (графема)

6. Сравнение строк Используйте StringComparison для явного указания правил сравнения, особенно в культурно-зависимых сценариях.

bool equal = string.Equals("test", "TEST", StringComparison.OrdinalIgnoreCase);

Практическое правило: При активной работе со строками (парсинг, построение) всегда оценивайте необходимость использования StringBuilder, ReadOnlySpan<char> (для .NET Core) или массивов символов.