¿Por qué las llaves en C# son un dolor de cabeza?
¿Alguna vez has escrito código en C#, querido mostrar texto como {Nombre}: {Valor}, y en su lugar obtuviste un FormatException? Si es así, no estás solo. La pregunta «How to escape curly brace in String.Format» en Stack Overflow ha acumulado decenas de miles de visitas. Y no es casualidad: las llaves {} en C# tienen un significado especial: indican un lugar para sustituir variables.
Pero, ¿qué hacer si necesitas mostrar las llaves mismas como caracteres normales? Por ejemplo, para JSON, plantillas, generación de código o simplemente para un formateo bonito de un informe. Hoy analizaremos este tema de principio a fin: desde el escape simple hasta trucos avanzados con StringBuilder e interpolación de cadenas.
Cómo escapar llaves: la regla básica
La respuesta es simple y elegante: duplica la llave. Si quieres mostrar una llave de apertura {, escribe {{. Para la de cierre }, escribe }}. C# entenderá que no es un marcador de posición, sino un carácter normal.
Aquí tienes el ejemplo más simple:
string result = string.Format("Valor entre llaves: {{0}}", 42);Console.WriteLine(result);// Salida: Valor entre llaves: {0}Observa: {{0}} no es un marcador de posición, sino un par de llaves escapadas con el dígito 0 dentro. Si hubiéramos escrito {0}, habríamos obtenido el valor de la variable (el número 42).
Error típico de principiante
A menudo los novatos escriben así:
// ¡ERROR!string bad = string.Format("¡Hola, {name}!", name);// FormatException: Input string was not in a correct format.¿Por qué? Porque C# espera un índice numérico dentro de las llaves ({0}, {1}), no un nombre de variable. Para nombres, debes usar interpolación de cadenas (más abajo) o indicar explícitamente los índices.
Ejemplos prácticos: de lo simple a lo complejo
Analicemos varios escenarios reales donde es necesario escapar llaves.
1. Mostrar JSON o XML con fines de depuración
Imagina que escribes un logger y quieres mostrar una cadena JSON sustituyendo un valor:
int userId = 101;string json = string.Format("{{\\"userId\\": {0}, \\"name\\": \\"Alice\\"}}", userId);Console.WriteLine(json);// Salida: {"userId": 101, "name": "Alice"}Aquí, {{ y }} crean las llaves externas del JSON, y {0} sustituye el número.
2. Generación de plantillas de código
Supón que escribes un generador de código en C#. Necesitas crear una cadena con una plantilla para otro lenguaje (por ejemplo, Python o JavaScript):
string template = string.Format("def {0}(): return {{0}}", "calculate");Console.WriteLine(template);// Salida:// def calculate():// return {0}Observa: {{0}} en la cadena de salida ya no es un marcador de posición de C#, sino parte del código generado (por ejemplo, para Python).
3. Formateo con múltiples marcadores y llaves
Cuando necesitas mezclar sustituciones y escapes, lo importante es no confundirse con los índices:
string name = "Bob";int age = 30;string message = string.Format("Usuario {{ {0} }} (edad: {1})", name, age);Console.WriteLine(message);// Salida: Usuario { Bob } (edad: 30)Aquí, {{ produce {, }} produce }, y {0} y {1} sustituyen los valores.
Alternativas a String.Format: interpolación de cadenas y StringBuilder
Aunque string.Format es un clásico, en C# moderno hay formas más cómodas. Comparemos.
Interpolación de cadenas (C# 6+)
La interpolación es la magia de $ antes de la cadena. Se lee mejor, pero el escape de llaves queda