Avatar ·

Как экранировать фигурные скобки в форматной строке в .NET (C#)

Всем привет! Я только начал изучать C# и столкнулся с проблемой при работе с методом `String.Format` (или интерполяцией строк). Мне нужно вывести текст, содержащий фигурные скобки, например, для генерации JSON-строки или шаблона HTML. Проблема в том, что когда я пишу такой код: ```csharp string result = String.Format("Значение: {0} и {1}", "A", "B"); Console.WriteLine(result); // Выводит: Значение: A и B ``` Всё работает. Но если я хочу вывести сами фигурные скобки, например, как часть строки "Значение: {0} и {1}", то компилятор или среда выполнения воспринимают их как плейсхолдеры для подстановки аргументов. Я пробовал просто ставить двойные скобки, но это не помогает — возникает исключение FormatException. Вот пример моего кода, который не работает: ```csharp string jsonTemplate = String.Format("{{\"name\": \"{0}\"}}", "Alice"); Console.WriteLine(jsonTemplate); // Ожидаю: {"name": "Alice"} // Получаю исключение: Input string was not in a correct format. ``` Я также пробовал интерполяцию строк ($"..."), но там та же проблема — скобки воспринимаются как часть выражения. Подскажите, как правильно экранировать фигурные скобки в форматных строках .NET? Заранее спасибо! <<>>

Решение: экранирование фигурных скобок через удвоение

В .NET фигурные скобки { и } являются специальными символами в форматных строках. Чтобы вывести их как обычный текст, нужно использовать двойные скобки: {{ для вывода одной { и }} для вывода одной }. Это правило работает как для метода String.Format, так и для интерполяции строк.

Рассмотрим ваш пример с JSON. Чтобы получить строку {"name": "Alice"}, нужно написать:

string name = "Alice";
string jsonTemplate = String.Format("{{ \"name\": \"{0}\" }}", name);
Console.WriteLine(jsonTemplate); // Вывод: { "name": "Alice" }

Как это работает:

  • {{ — экранирует одну открывающую скобку {.
  • }} — экранирует одну закрывающую скобку }.
  • {0} — это плейсхолдер для подстановки аргумента (здесь — переменной name).

Интерполяция строк ($"...")

То же самое работает и с интерполяцией, но с одним важным нюансом: если вы используете $, то двойные скобки экранируются так же, но плейсхолдеры выглядят как {выражение}:

string name = "Alice";
string jsonTemplate = $"{{ \"name\": \"{name}\" }}";
Console.WriteLine(jsonTemplate); // Вывод: { "name": "Alice" }

Обратите внимание: {{ и }} экранируют скобки, а {name} — это уже подстановка значения переменной.

Практические примеры

Пример 1. Генерация HTML-шаблона:

string title = "Мой сайт";
string html = String.Format("<div class=\"container\">{{0}}</div>", title);
Console.WriteLine(html); // Вывод: <div class="container">Мой сайт</div>

Пример 2. Вывод математической формулы:

int a = 5, b = 3;
string formula = $"{{ {a} + {b} = {a + b} }}";
Console.WriteLine(formula); // Вывод: { 5 + 3 = 8 }

Важные правила

  • Количество экранирующих скобок должно быть чётным. {{{0}}} — это ошибка (3 скобки). Нужно {{{0}}}? Нет, правильно: {{{0}}} — это две экранирующие ({{ и }}) и плейсхолдер {0}. Фактически это 4 символа: {{, {0}, }}.
  • Если вам нужно вывести две скобки подряд, используйте {{{{ (четыре скобки дадут две).
  • В .NET 6+ появился новый синтаксис String.Create, но для большинства задач удвоение — самый простой и читаемый способ.

Альтернативный подход: StringBuilder

Если вы часто работаете со сложными шаблонами, можно использовать StringBuilder с методом AppendFormat — правила экранирования те же:

var sb = new StringBuilder();
sb.AppendFormat("{{0}}", "значение"); // Вывод: {0}
Console.WriteLine(sb.ToString());

В итоге, запомните простое правило: две скобки = одна скобка. Это универсальный способ для всех версий .NET.

<<>>

Использование строковых констант и условной замены

Если вам нужно много раз выводить фигурные скобки, и вы хотите избежать путаницы с двойными скобками, можно заранее определить константы для скобок и использовать обычную конкатенацию или метод Replace.

Пример с константами:

const string LBRACE = "{";
const string RBRACE = "}";
string name = "Alice";
string json = LBRACE + $" \"name\": \"{name}\" " + RBRACE;
Console.WriteLine(json); // Вывод: { "name": "Alice" }

Этот подход особенно полезен, если вы генерируете JSON или XML вручную и хотите сохранить читаемость кода. Однако помните, что для больших объёмов данных лучше использовать сериализаторы (например, System.Text.Json).

Альтернатива: метод Replace после форматирования

Вы можете сначала создать шаблон с уникальными маркерами, а потом заменить их на скобки:

string template = "##name## \"name\": \"{0}\" ##/name##";
string result = String.Format(template, "Alice")
                     .Replace("##name##", "{")
                     .Replace("##/name##", "}");
Console.WriteLine(result); // Вывод: { "name": "Alice" }

Этот способ менее производительный, но удобен, когда нужно экранировать много вложенных скобок или когда шаблон приходит из внешнего источника.

Важно: Для работы с JSON, XML или другими структурированными данными всегда используйте специализированные библиотеки (Newtonsoft.Json, System.Text.Json, XmlSerializer и т.д.) — это безопаснее и предотвращает ошибки форматирования.