Однажды на Stack Overflow: Проклятие длинных строк в C#
Представьте ситуацию. Вы пишете на C# конфигурационный JSON, SQL-запрос или, скажем, HTML-шаблон прямо в коде. Строка получается длинной, некрасивой и абсолютно нечитаемой. Вы нажимаете Enter, чтобы перенести текст... и получаете ошибку компиляции. Знакомо?
Вопрос "Multiline string literal in C#" на Stack Overflow собрал десятки тысяч просмотров. И это не случайно. Долгое время C# был не самым дружелюбным языком для работы с многострочным текстом. Но времена меняются. В этой статье мы пройдем путь от костылей до элегантных решений, которые появились в C# 11.
Если вы пишете на C# и работаете с многострочными строковыми литералами, этот материал сэкономит вам часы гугления. Поехали!
Проблема: Почему просто нажать Enter — плохая идея?
В C# (как и в C++) строковый литерал — это последовательность символов, заключенная в кавычки. Перенос строки внутри таких кавычек — это синтаксическая ошибка. Компилятор просто не поймет, где заканчивается строка.
Вот как НЕ надо делать:
// Ошибка компиляции!
string query = "SELECT * FROM Users
WHERE Age > 18
ORDER BY Name";
Компилятор увидит "SELECT * FROM Users — и всё. Дальше идет мрак. Раньше разработчики выкручивались как могли. Давайте разберем эволюцию решений.
Старый способ: Verbatim string (@-строка) — палочка-выручалочка
Первое, что приходит на ум — это verbatim string literal. Вы просто ставите @ перед открывающей кавычкой. Это отключает интерпретацию escape-последовательностей (кроме двойных кавычек "").
Но есть нюанс: отступы тоже становятся частью строки.
Пример с verbatim string:
string json = @"{
""name"": ""Alice"",
""age"": 30
}";
Console.WriteLine(json);
Вывод:
{
"name": "Alice",
"age": 30
}
Плюсы:
- Работает во всех версиях C#.
- Не нужно экранировать обратную косую черту (
\).
Минусы:
- Кавычки внутри приходится удваивать (
"") — это ужасно, если много JSON. - Отступы слева (пробелы/табуляции) попадают в итоговую строку.
- Нельзя смешивать с интерполяцией строк (
$) напрямую (но можно$@).
Этот метод до сих пор популярен, но для чистого кода он не идеален. Настоящий прорыв случился в C# 11.
Новейший способ: Raw string literal (C# 11 и .NET 7+)
Начиная с C# 11, у нас есть raw string literal — буквально "сырой строковый литерал". Он решает 99% проблем многострочности.
Синтаксис: три и более двойных кавычки подряд (""").
Пример 1: Простой JSON без экранирования
string json = """
{
"name": "Alice",
"age": 30
}
""";
Console.WriteLine(json);
Вывод:
{
"name": "Alice",
"age": 30
}
Магия: Кавычки внутри строки не нужно удваивать! Компилятор понимает, что строка закончилась, только когда видит три кавычки подряд.
Пример 2: SQL-запрос с отступами
string query = """
SELECT
u.Name,
o.OrderDate
FROM Users u
JOIN Orders o ON u.Id = o.UserId
WHERE o.Status = 'Active'
ORDER BY o.OrderDate DESC
""";
Console.WriteLine(query);
Важно про отступы: Закрывающие кавычки (""") задают базовый уровень отступа. Все строки, которые имеют отступ меньше, чем закрывающие кавычки, будут обрезаны. Это позволяет сохранить читаемость кода, не захламляя строку лишними пробелами.
Пример 3: Интерполяция в raw string
Да, вы можете смешивать raw string literals с интерполяцией. Для этого нужно поставить знак доллара и то количество кавычек, которое не конфликтует с фигурными скобками.
string name = "Bob";
int age = 25;
string message = $$"""
Hello, {{name}}!
You are {{age}} years old.
""";
Console.WriteLine(message);
Вывод:
Hello, Bob!
You are 25 years old.
Если вы используете $$ и {{ }}, то одинарные фигурные скобки { } внутри строки воспринимаются как обычные символы.
Сравнение методов: от старины до современности
Давайте сведем всё в таблицу (мысленно, но наглядно).
| Метод | Версия C# | Экранирование кавычек | Отступы | Интерполяция |
|---|---|---|---|---|
string + "\n" | Все | Нормальное | Ручное | Да |
@"" (Verbatim) | Все | Удвоение "" | Сохраняются | Через $@ |
""" """ (Raw) | C# 11+ | Не нужно | Авто-удаление | Через $$ |
Вывод: Если ваш проект на .NET 7 или новее — используйте raw string literal. Это самый чистый и современный способ.
Когда старые методы еще имеют смысл?
Не спешите удалять @-строки из памяти. Есть сценарии, где они удобнее:
- Короткие пути к файлам:
@"C:\Users\Public\file.txt"— короче, чем"""C:\Users\Public\file.txt""". - Старые проекты: Если вы застряли на .NET Framework 4.x, raw string literals вам недоступны.
- Одиночные строки с кавычками