Menu

Interpolación de strings y String.Format en C#: especificadores de formato, alineación y cultura

Cómo funciona la interpolación de strings $"..." en C#: expresiones entre llaves, especificadores de formato como F2, N0, C, D5 y X, alineación para tablas, escapar llaves, string.Format y el formato compuesto, strings interpolados literales y sin procesar, y dar formato para una cultura concreta.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

La interpolación de strings construye un string a partir de texto literal y expresiones. Pon el prefijo $ al literal, escribe cualquier expresión de C# entre llaves, y su valor se convierte a texto y se inserta:

Salida:

Hello, Maya!
3 items at 4.5 = 13.5
Name has 4 letters, upper: MAYA
Free shipping: yes

La interpolación llegó en C# 6. El compilador la convierte en una llamada a string.Format o string.Concat (o, desde C# 10, en código de handlers más eficiente), así que no es más lenta que construir el string a mano.

La expresión condicional de la última línea necesita paréntesis. Dentro de un hueco de interpolación, los dos puntos inician un especificador de formato, así que {x > 10 ? "yes" : "no"} sin paréntesis es un error de compilación.

Especificadores de formato

Después de la expresión, unos dos puntos y un string de formato controlan cómo se escribe el valor. Los mismos strings de formato funcionan con ToString("...") y con string.Format.

Salida:

1234567.89
1,234,567.89
1,234,568
00042
FF
00ff
1.23E+006
0.813
81.3%
1,234,567.89
007.5
3.1

Los códigos estándar, cada uno seguido opcionalmente de un número de precisión:

CódigoNombreEjemploResultado
F o F2Punto fijo{3.14159:F2}3.14
N o N0Número con separadores de grupo{1234.56:N0}1,235
CMoneda (símbolo y patrón de la cultura){9.5:C} en en-US$9.50
D5Entero rellenado con ceros{42:D5}00042
X, xHexadecimal{255:X}FF
E2Científico{1234.5:E2}1.23E+003
P1Porcentaje (multiplica por 100){0.256:P1} en en-US25.6%
GGeneral (el más corto){2.50m:G}2.50
RIda y vuelta (double){0.1:R}0.1

Los patrones propios construyen un formato a partir de marcadores: 0 es un dígito que siempre se muestra, # es un dígito que solo se muestra si es significativo, . es el punto decimal, , dentro del número activa los separadores de grupo y % multiplica por 100. "0.##" muestra hasta dos decimales y quita los ceros finales; "#,##0.00" es el formato contable clásico.

Todo el formato numérico redondea el valor mostrado; la variable en sí no cambia. Cuando un valor está justo a medio camino (2,25 mostrado con un decimal), distintos runtimes y tipos pueden redondear el empate de forma distinta, así que si la regla importa, redondea antes de forma explícita con Math.Round(value, 1, MidpointRounding.AwayFromZero) y después da formato.

Fechas en la interpolación

Los valores DateTime aceptan strings de formato de fecha de la misma forma:

Salida:

2026-09-24
24/09/2026 16:05
Thu, Sep 24
Shipped at 16:05 on Thursday
ETA 02:10
2.2 hours

Un formato propio de TimeSpan exige escapar los caracteres literales con una barra invertida, que en un literal de string normal se escribe \\:. La lista completa de códigos de fecha (yyyy, MM, HH, tt...) y los errores que se cometen con ellos (mm son minutos, MM son meses) están en formato de DateTime.

Alineación y relleno

Una coma después de la expresión fija un ancho mínimo de campo. Un número positivo alinea a la derecha y uno negativo a la izquierda. Combinado con un formato, alinea tablas en texto plano:

Salida:

Item          |  Price| Sold
----------------------------
Espresso      |   2.40|  118
Latte         |   3.60|   64
Hot chocolate |   4.25|    9

La sintaxis es {expression,alignment:format}: primero la alineación, después el formato. Un valor más largo que el ancho no se recorta; empuja el resto de la línea. PadLeft y PadRight hacen el mismo relleno fuera de la interpolación.

Escapar las llaves

Para imprimir una llave literal, duplícala: {{ y }}. Esto aparece cuando la salida es JSON, CSS o código:

Salida:

{ "id": 42, "name": "Ana" }
Set literal: {1, 2, 3}
{42}

Construir JSON a mano así vale para una línea de log rápida; para JSON de verdad usa un serializador, que maneja correctamente las comillas y los caracteres especiales dentro de name.

string.Format y el formato compuesto

Antes de C# 6, el formato se hacía con string.Format, que recibe marcadores numerados y una lista de argumentos. La misma sintaxis de formato compuesto la aceptan Console.WriteLine, StringBuilder.AppendFormat y TextWriter.Write:

Salida:

Notebook x4: 14.00
Notebook  |  3.50
echo echo !
Dear Leo, your order #000731 has shipped.

En el código, prefiere la interpolación: los valores están donde aparecen, así que un marcador no puede apuntar al argumento equivocado. string.Format sigue siendo la herramienta correcta cuando la plantilla es un dato, como un mensaje traducido cargado de un archivo de recursos. Un índice de marcador sin argumento correspondiente ({2} con dos argumentos) lanza una FormatException en tiempo de ejecución.

Cultura: controlar los separadores y la moneda

La interpolación, ToString y string.Format usan por defecto la cultura actual del hilo. En una máquina configurada en alemán, {1234.5:N2} produce 1.234,50; en Estados Unidos produce 1,234.50. El formato de moneda C usa el símbolo de la cultura. Para elegir la cultura de forma explícita, captura el string interpolado como un FormattableString y dale formato con un proveedor:

Salida:

Total: 1,234.50
Total: 1.234,50
$1,234.50
1.234,50
1234.5,0.75

Usa la cultura del usuario para el texto que leen las personas, y CultureInfo.InvariantCulture para todo lo que lee otro programa. Un CSV escrito con la cultura actual en una máquina en alemán tiene comas dentro de los números y no se puede leer en otro sitio. En .NET 6 y posteriores, string.Create(CultureInfo.InvariantCulture, $"...") hace lo mismo que FormattableString.Invariant sin el objeto intermedio.

Strings interpolados literales y sin procesar

$ se combina con @ para un string interpolado literal (verbatim): las barras invertidas son literales y el string puede ocupar varias líneas. C# 8 y posteriores aceptan los dos órdenes ($@ o @$); C# 6 y 7 exigen $@:

Salida:

C:\Users\ana\Reports\2026\summary.txt
Report for ana
Year: 2026

C# 11 añadió los strings interpolados sin procesar. Con un $, las llaves marcan expresiones como siempre. Con $$, una llave simple es literal y las expresiones necesitan dos llaves, lo que hace legibles las plantillas de JSON y de código:

// C# 11 and later
int id = 42;
string name = "Ana";
string json = $$"""
    {
      "id": {{id}},
      "name": "{{name}}"
    }
    """;

C# 11 también permite saltos de línea dentro de un hueco de interpolación, así que una expresión larga o una expresión switch pueden repartirse en varias líneas.

Errores comunes

  • Olvidar el $. "Total: {total}" imprime las llaves literalmente. El compilador no avisa.
  • Un ternario sin paréntesis dentro de las llaves: los dos puntos se leen como separador de formato.
  • Dar formato a la salida legible por máquinas con la cultura actual. Las comas decimales rompen CSV, JSON y SQL. Usa la cultura invariante.
  • Usar ToString() sin formato para el dinero. 2.5m se imprime como 2.5, no 2.50. Usa F2, N2 o C.
  • Construir strings grandes con interpolación dentro de un bucle. Cada iteración crea un string nuevo; usa StringBuilder o string.Join.

Preguntas frecuentes

¿Qué es la interpolación de strings en C#?

Un literal de string con el prefijo $ en el que las expresiones entre llaves se evalúan e insertan: $"Total: {price * qty}". Se añadió en C# 6 y sustituye a la mayoría de los usos de string.Format y de la concatenación con +. Dentro de las llaves funciona cualquier expresión, incluidas las llamadas a métodos y el acceso a propiedades.

¿Cómo formateo un número con 2 decimales en C#?

Añade un especificador de formato después de dos puntos: $"{price:F2}" imprime 2 dígitos después del punto decimal, y $"{price:N2}" hace lo mismo con separadores de miles. Fuera de la interpolación, los mismos códigos funcionan con price.ToString("F2"). Los dos redondean el valor para mostrarlo sin cambiarlo.

¿Cómo escapo las llaves en un string interpolado de C#?

Duplícalas: {{ imprime { y }} imprime }. Por ejemplo, $"{{ \"id\": {id} }}" imprime { "id": 42 }. En los strings interpolados sin procesar de C# 11 puedes empezar el literal con $$, de modo que las llaves simples son literales y {{expr}} marca una expresión.

¿Qué diferencia hay entre string.Format y la interpolación de strings?

Producen el mismo resultado con los mismos códigos de formato. string.Format("{0} costs {1:F2}", name, price) se refiere a los argumentos por posición; $"{name} costs {price:F2}" pone las expresiones en línea, así que se lee mejor y no puede equivocarse en el orden de los argumentos. string.Format sigue siendo necesario cuando el propio string de formato viene de un archivo de recursos o de una base de datos.

¿Por qué mi número interpolado muestra una coma en lugar de un punto?

La interpolación da formato con la cultura actual del hilo, y muchas culturas usan la coma como separador decimal. Para la salida que leen las máquinas (archivos, JSON, URL), da formato con la cultura invariante: FormattableString.Invariant($"{value:F2}"), o en .NET 6 y posteriores string.Create(CultureInfo.InvariantCulture, $"...").

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR