Avatar ·

Многострочные строковые литералы в C#: как записать длинный текст без экранирования?

Привет, коллеги! Я новичок в C# и столкнулся с проблемой. Мне нужно сохранить в переменную длинный текст, например, SQL-запрос, JSON или просто многострочное сообщение. В других языках (Python, JavaScript) я могу использовать тройные кавычки или шаблонные строки, и там всё работает красиво. Но в C# я не могу найти удобного способа. Вот пример того, что я пытаюсь сделать: ```csharp string query = "SELECT * FROM Users WHERE Age > 18 ORDER BY Name;"; ``` Компилятор выдаёт ошибку, потому что нельзя переносить строку внутри двойных кавычек. Я пробовал использовать символ `\n`: ```csharp string query = "SELECT * FROM Users\nWHERE Age > 18\nORDER BY Name;"; ``` Но это работает, только если я хочу одну строку с переносами, а не читаемый многострочный код. В реальном проекте у меня есть большие фрагменты XML и JSON, где экранирование кавычек и спецсимволов превращается в ад. Например: ```csharp string json = "{\"name\": \"John\",\n\"age\": 30,\n\"city\": \"New York\"}"; ``` Это нечитаемо и трудно поддерживаемо. Я знаю про `StringBuilder`, но это жестоко для простых констант. Есть ли в C# какой-то синтаксический сахар для многострочных строк? Может быть, я пропустил какую-то фичу из последних версий языка? Буду благодарен за примеры кода с пояснениями. <<>>

Решение: вербатимные строки (verbatim strings) и необработанные строковые литералы (raw string literals)

В C# есть два отличных способа работать с многострочным текстом. Первый — это вербатимные строки (добавлены с C# 1.0), второй — необработанные строковые литералы (появились в C# 11). Рассмотрим оба.

1. Вербатимные строки с префиксом @

Если поставить символ @ перед открывающей кавычкой, строка становится "буквальной" — все символы внутри интерпретируются как есть, включая переносы строк. Экранирование кавычек делается удвоением: "".

string query = @"SELECT * FROM Users
WHERE Age > 18
ORDER BY Name;";

string json = @"{
    ""name"": ""John"",
    ""age"": 30,
    ""city"": ""New York""
}";

Console.WriteLine(query);
Console.WriteLine(json);

Обратите внимание: открывающая кавычка должна быть на той же строке, что и @, иначе в начале строки появится лишний перенос. Удвоение кавычек ("") — это единственное неудобство, но для SQL-запросов или текста с редкими кавычками это нормально.

2. Необработанные строковые литералы (C# 11 и .NET 7+)

Это современный и самый чистый способ. Используются тройные кавычки """. Внутри можно писать любой текст без экранирования, включая кавычки (кроме последовательности из трёх кавычек подряд). Переносы строк сохраняются как есть.

string query = """
    SELECT * FROM Users
    WHERE Age > 18
    ORDER BY Name;
    """;

string json = """
    {
        "name": "John",
        "age": 30,
        "city": "New York"
    }
    """;

Console.WriteLine(query);
Console.WriteLine(json);

Важные детали:

  • Открывающие """ должны быть на отдельной строке, и после них сразу идёт перевод строки.
  • Закрывающие """ тоже на отдельной строке. Отступ внутри строки определяется отступом закрывающих кавычек — весь текст будет выровнен относительно них. Это позволяет красиво форматировать код.
  • Если нужно включить в текст три кавычки подряд, их можно экранировать, но на практике это редко требуется.

Пример с интерполяцией (C# 11):

string name = "Alice";
int age = 25;
string message = $$"""
    Hello, {{name}}!
    You are {{age}} years old.
    """;
Console.WriteLine(message); // Hello, Alice! You are 25 years old.

Обратите внимание на $$ — это маркер интерполяции для необработанных строк. Количество знаков $ определяет, сколько фигурных скобок нужно для подстановки.

Когда что использовать?

  • Если ваш проект на старой версии C# (до 11) — используйте @"". Это надёжно и работает везде.
  • Если у вас C# 11+ и вы пишете JSON, XML, SQL, конфиги — используйте """. Это чище и не требует удвоения кавычек.

Больше не нужно мучиться с \n и экранированием. Выбирайте подходящий вариант и пишите читаемый код!

<<>>

Альтернативный подход: использование констант и ресурсов

Если многострочный текст очень большой (например, шаблон HTML, длинный SQL-запрос или полный JSON-файл), лучше не хранить его прямо в коде, а вынести в отдельный файл или ресурс.

Вариант 1: Файл с встраиванием (Embedded Resource)
Добавьте файл query.sql в проект, установите свойство "Build Action" = "Embedded Resource". Затем читайте его так:

using System.Reflection;

string query;
var assembly = Assembly.GetExecutingAssembly();
using (var stream = assembly.GetManifestResourceStream("YourNamespace.query.sql"))
using (var reader = new StreamReader(stream))
{
    query = reader.ReadToEnd();
}

Вариант 2: Raw string literal с файлом
В C# 11 можно использовать """ и сохранить текст в отдельной переменной в том же файле, но для больших объёмов лучше держать их отдельно для удобства редактирования.

Вариант 3: Константы с помощью nameof и ресурсов
Для строк, которые не меняются, можно использовать файлы .resx (ресурсы проекта). Это даёт типобезопасный доступ через Properties.Resources.Query.

Этот подход особенно полезен, когда текст содержит много кавычек или спецсимволов, а также когда над проектом работает команда — проще править отдельный файл, чем лазить в код.