Что такое string в C# и каковы его особенности?

Ответ

В C# string (System.String) — это ссылочный тип данных, представляющий неизменяемую (immutable) последовательность символов UTF-16.

Ключевые особенности:

  1. Неизменяемость (Immutability):

    • Это самая важная характеристика. После создания строку нельзя изменить. Любая операция, которая кажется изменяющей строку (ToUpper(), Replace(), +=), на самом деле возвращает совершенно новый объект строки в памяти.
      string s1 = "Hello";
      string s2 = s1.ToUpper(); // s1 остаётся "Hello", s2 — новый объект "HELLO"
      s1 += " World"; // Создаётся новая строка "Hello World", s1 теперь ссылается на неё
    • Преимущества: потокобезопасность, простота, возможность хеширования и использования в качестве ключей словаря.
    • Недостаток: потенциальные накладные расходы на память и производительность при частой конкатенации в циклах. Решение — StringBuilder.
  2. Сравнение по значению:

    • Хотя string — ссылочный тип, операторы == и != перегружены для сравнения содержимого строк, а не ссылок.
      string a = "test";
      string b = "test";
      Console.WriteLine(a == b); // True (сравнение значений)
      Console.WriteLine(object.ReferenceEquals(a, b)); // Может быть True из-за интернирования
  3. Интернирование строк (String Interning):

    • CLR поддерживает пул строк (intern pool). При создании строкового литерала среда выполнения проверяет, есть ли такая же строка в пуле. Если есть — возвращает ссылку на существующий объект. Это экономит память.
    • Интернирование можно принудительно вызвать: string.Intern() и string.IsInterned().
  4. Форматирование и интерполяция:

    • Интерполяция строк (C# 6+): Удобный и производительный способ вставки значений.
      string name = "Alice";
      int age = 30;
      string message = $"Меня зовут {name} и мне {age} лет.";
    • Компилируется в вызов string.Format или, для простых случаев, в более эффективную конкатенацию.
  5. Пустая строка и null:

    • string.Empty (или "") — корректный, пустой объект строки с нулевой длиной.
    • null — отсутствие ссылки на какой-либо объект строки.
    • Используйте string.IsNullOrEmpty() или string.IsNullOrWhiteSpace() для проверки.

Практический совет: Для интенсивной работы со строками (много операций конкатенации, особенно в циклах) используйте StringBuilder.

// ПЛОХО (создаётся много промежуточных строк):
string result = "";
for (int i = 0; i < 100; i++) result += i.ToString();

// ХОРОШО (создаётся один буфер):
var sb = new StringBuilder();
for (int i = 0; i < 100; i++) sb.Append(i);
string result = sb.ToString();

Ответ 18+ 🔞

Ну что за тема, про строки в C#! Сидишь такой, думаешь: "Ну строка и строка, буквы там, текст". Ан нет, тут целая философия, блядь!

Смотри, string — это ж ссылочный тип, да. Но ведёт себя местами как приличный, а местами — ну просто пиздец какой хитрожопый. Представь себе стеклянную вазу, дорогую такую. Ты на неё смотришь, любуешься, но тронуть — хуй. Это и есть неизменяемость, главная фишка.

Вот пишешь ты:

string s1 = "Hello";
string s2 = s1.ToUpper();

И думаешь: "О, s1 теперь большими буквами!" А нихуя! s1 так и осталась маленькой, скромной. А s2 — это уже новая ваза, блядь, которую тебе выдули на заводе, с надписью "HELLO". Каждая операция, которая якобы меняет строку — Replace(), Trim(), эта конкатенация через += — это просто пиздец, новый объект в памяти! Представляешь, сколько мусора, если в цикле это делать? У меня волосы дыбом встают, ей-богу.

А про сравнение вообще отдельный цирк. Вроде ссылочный тип, должен по ссылкам сравниваться. А тут взяли, перегрузили операторы == и !=, и теперь они сравнивают не адреса в памяти, а реальный текст внутри! Удобно, конечно, но когда впервые сталкиваешься — мозг ебёт немного.

string a = "test";
string b = "test";
Console.WriteLine(a == b); // True — потому что буквы одинаковые!

А ещё есть интернирование, этакая магия CLR. Возьмёт твои строковые литералы, сложит в общий бассейн, и если две переменные на одно и то же слово ссылаются — могут и одну память использовать. Хитро, да? Экономия, блядь. Но надеяться на это в логике — себя не уважать.

Самое охуенное, что придумали — интерполяция строк. Раньше писали string.Format("Меня зовут {0}, мне {1} лет", name, age), глаза сломать можно было. А теперь — красота:

string message = $"Меня зовут {name} и мне {age} лет.";

Чисто, понятно. Компилятор это всё разворачивает в нормальный код, иногда даже эффективнее, чем вручную.

И главный практический совет, который спасёт тебе жизнь: не ебись с конкатенацией в циклах! Серьёзно.

Вот смотри, как делать НЕ НАДО (так делают только упоротые или те, кому похуй на память):

string result = "";
for (int i = 0; i < 100; i++) result += i.ToString();

Здесь на каждой итерации старая строка в мусор, новая создаётся. Производительность летит в пизду, сборщик мусора плачет.

А вот как надо — с StringBuilder:

var sb = new StringBuilder();
for (int i = 0; i < 100; i++) sb.Append(i);
string result = sb.ToString();

Один объект, один буфер, всё быстро и чётко. Запомни это как "Отче наш".

И да, проверяй строки на пустоту правильно. Не if (str == ""), и уж тем более не if (str == null || str == ""). Есть же готовые методы, блядь:

if (string.IsNullOrEmpty(str)) { ... }
if (string.IsNullOrWhiteSpace(str)) { ... } // этот ещё и пробелы с табами отсечёт

Короче, строка — она как девушка с характером. Кажется простой, но если не знать её особенностей — обосрёшься по полной. Держи ухо востро, и будет тебе счастье.