Interpolación de cadenas en C#

En este tutorial se explica cómo usar la interpolación de cadenas para dar formato a resultados de expresión e incluirlos en una cadena de resultado. En los ejemplos se da por hecho que ya está familiarizado con los conceptos básicos de C# y el formato de tipos .NET. Si no conoce la interpolación de cadenas o el formato de tipos .NET, vea antes el tutorial de interpolación de cadenas interactivo. Para más información sobre cómo aplicar formato a tipos .NET, vea el tema Aplicar formato a tipos en .NET.

Introducción

Para distinguir un literal de cadena como una cadena interpolada, antepóngale el símbolo $. Puede insertar cualquier expresión de C# válida que devuelva un valor en una cadena interpolada. En el siguiente ejemplo, en cuanto la expresión se evalúa, su resultado se convierte en una cadena y se incluye en una cadena de resultado:

double a = 3;
double b = 4;
Console.WriteLine($"Area of the right triangle with legs of {a} and {b} is {0.5 * a * b}");
Console.WriteLine($"Length of the hypotenuse of the right triangle with legs of {a} and {b} is {CalculateHypotenuse(a, b)}");
double CalculateHypotenuse(double leg1, double leg2) => Math.Sqrt(leg1 * leg1 + leg2 * leg2);
// Output:
// Area of the right triangle with legs of 3 and 4 is 6
// Length of the hypotenuse of the right triangle with legs of 3 and 4 is 5

Como se ilustra en el ejemplo, para incluir una expresión en una cadena interpolada hay que meterla entre llaves:

{<interpolationExpression>}

Las cadenas interpoladas admiten todas las funcionalidades de la característica de formato compuesto de cadena. Esto las convierte en una alternativa más legible al uso del método String.Format.

Cómo especificar una cadena de formato para una expresión de interpolación

Para especificar una cadena de formato compatible con el tipo del resultado de la expresión, siga la expresión de interpolación con dos puntos (":") y la cadena de formato:

{<interpolationExpression>:<formatString>}

En el siguiente ejemplo se muestra cómo especificar cadenas de formato estándar y personalizadas para expresiones que generan resultados numéricos o de fecha y hora:

var date = new DateTime(1731, 11, 25);
Console.WriteLine($"On {date:dddd, MMMM dd, yyyy} L. Euler introduced the letter e to denote {Math.E:F5}.");
// Output:
// On Sunday, November 25, 1731 L. Euler introduced the letter e to denote 2.71828.

Para más información, consulte la sección Componente de cadena de formato del artículo Formato compuesto.

Cómo controlar el ancho de campo y la alineación de las expresiones de interpolación con formato

Para especificar la anchura mínima del campo y la alineación del resultado de la expresión formateada, siga la expresión de interpolación con una coma (",") y la expresión constante:

{<interpolationExpression>,<alignment>}

Si el valor de alignment es positivo, el resultado de la expresión con formato se alineará a la derecha y, si es negativo, lo hará a la izquierda.

En caso de que haya que especificar una alineación y una cadena de formato, comience por el componente de alineación:

{<interpolationExpression>,<alignment>:<formatString>}

En el siguiente ejemplo se muestra cómo especificar la alineación y se emplean caracteres de barra vertical ("|") para delimitar los campos de texto:

const int NameAlignment = -9;
const int ValueAlignment = 7;
double a = 3;
double b = 4;
Console.WriteLine($"Three classical Pythagorean means of {a} and {b}:");
Console.WriteLine($"|{"Arithmetic",NameAlignment}|{0.5 * (a + b),ValueAlignment:F3}|");
Console.WriteLine($"|{"Geometric",NameAlignment}|{Math.Sqrt(a * b),ValueAlignment:F3}|");
Console.WriteLine($"|{"Harmonic",NameAlignment}|{2 / (1 / a + 1 / b),ValueAlignment:F3}|");
// Output:
// Three classical Pythagorean means of 3 and 4:
// |Arithmetic|  3.500|
// |Geometric|  3.464|
// |Harmonic |  3.429|

Tal y como refleja la salida del ejemplo, si la longitud del resultado de expresión con formato supera el ancho de campo especificado, se omitirá el valor de alignment.

Para más información, vea la sección Alignment (Componente) del tema Formatos compuestos.

Cómo usar secuencias de escape en una cadena interpolada

Las cadenas interpoladas admiten todas las secuencias de escape que se usan en los literales de cadena ordinarios. Para más información, vea Secuencias de escape de cadena.

Para interpretar las secuencias de escape literalmente, use un literal de cadena textual. Una cadena textual interpolada comienza con los $ caracteres y @. Los tokens $ y @ se pueden usar en cualquier orden; tanto $@"..." como @$"..." son cadenas textuales interpoladas válidas.

Para incluir una llave ("{" o "}") en una cadena de resultado, use dos llaves ("{{" o "}}"). Para más información, vea la sección Llaves de escape del artículo Formatos compuestos.

En el siguiente ejemplo se muestra cómo incluir llaves en una cadena de resultado y cómo construir una cadena interpolada textual:

var xs = new int[] { 1, 2, 7, 9 };
var ys = new int[] { 7, 9, 12 };
Console.WriteLine($"Find the intersection of the {{{string.Join(", ",xs)}}} and {{{string.Join(", ",ys)}}} sets.");
// Output:
// Find the intersection of the {1, 2, 7, 9} and {7, 9, 12} sets.

var userName = "Jane";
var stringWithEscapes = $"C:\\Users\\{userName}\\Documents";
var verbatimInterpolated = $@"C:\Users\{userName}\Documents";
Console.WriteLine(stringWithEscapes);
Console.WriteLine(verbatimInterpolated);
// Output:
// C:\Users\Jane\Documents
// C:\Users\Jane\Documents

A partir de C# 11, puede utilizar literales de cadena crudos interpolados.

Cómo usar un operador condicional ternario ?: en una expresión de interpolación

Dado que los dos puntos (:) tienen un significado especial en un elemento con una expresión de interpolación, para poder usar un operador condicional en una expresión de este tipo habrá que ponerlo entre paréntesis, como vemos en el siguiente ejemplo:

var rand = new Random();
for (int i = 0; i < 7; i++)
{
    Console.WriteLine($"Coin flip: {(rand.NextDouble() < 0.5 ? "heads" : "tails")}");
}

Cómo crear una cadena de resultado específica de la referencia cultural con interpolación de cadenas

Las cadenas interpoladas usan de forma predeterminada la referencia cultural definida actualmente por la propiedad CultureInfo.CurrentCulture en todas las operaciones de formato.

A partir de .NET 6, puede usar el String.Create(IFormatProvider, DefaultInterpolatedStringHandler) método para resolver una cadena interpolada en una cadena de resultado específica de la referencia cultural, como se muestra en el ejemplo siguiente:

var cultures = new System.Globalization.CultureInfo[]
{
    System.Globalization.CultureInfo.GetCultureInfo("en-US"),
    System.Globalization.CultureInfo.GetCultureInfo("en-GB"),
    System.Globalization.CultureInfo.GetCultureInfo("nl-NL"),
    System.Globalization.CultureInfo.InvariantCulture
};
var date = DateTime.Now;
var number = 31_415_926.536;
foreach (var culture in cultures)
{
    var cultureSpecificMessage = string.Create(culture, $"{date,23}{number,20:N3}");
    Console.WriteLine($"{culture.Name,-10}{cultureSpecificMessage}");
}
// Output is similar to:
// en-US       8/27/2023 12:35:31 PM      31,415,926.536
// en-GB         27/08/2023 12:35:31      31,415,926.536
// nl-NL         27-08-2023 12:35:31      31.415.926,536
//               08/27/2023 12:35:31      31,415,926.536

En versiones anteriores de .NET, utilice la conversión implícita de una cadena interpolada a una instancia System.FormattableString y llame a su método ToString(IFormatProvider) para crear una cadena de resultados específica de una cultura. En el siguiente ejemplo se muestra cómo hacerlo:

var cultures = new System.Globalization.CultureInfo[]
{
    System.Globalization.CultureInfo.GetCultureInfo("en-US"),
    System.Globalization.CultureInfo.GetCultureInfo("en-GB"),
    System.Globalization.CultureInfo.GetCultureInfo("nl-NL"),
    System.Globalization.CultureInfo.InvariantCulture
};
var date = DateTime.Now;
var number = 31_415_926.536;
FormattableString message = $"{date,23}{number,20:N3}";
foreach (var culture in cultures)
{
    var cultureSpecificMessage = message.ToString(culture);
    Console.WriteLine($"{culture.Name,-10}{cultureSpecificMessage}");
}
// Output is similar to:
// en-US       8/27/2023 12:35:31 PM      31,415,926.536
// en-GB         27/08/2023 12:35:31      31,415,926.536
// nl-NL         27-08-2023 12:35:31      31.415.926,536
//               08/27/2023 12:35:31      31,415,926.536

Tal y como se muestra en el ejemplo, se puede usar una instancia de FormattableString para generar varias cadenas de resultado para varias referencias culturales.

Cómo crear una cadena de resultado usando la referencia de cultura invariable

A partir de .NET 6, use el String.Create(IFormatProvider, DefaultInterpolatedStringHandler) método para resolver una cadena interpolada en una cadena de resultado para InvariantCulture, como se muestra en el ejemplo siguiente:

string message = string.Create(CultureInfo.InvariantCulture, $"Date and time in invariant culture: {DateTime.Now}");
Console.WriteLine(message);
// Output is similar to:
// Date and time in invariant culture: 05/17/2018 15:46:24

En versiones anteriores de .NET, junto con el FormattableString.ToString(IFormatProvider) método , puede usar el método estático FormattableString.Invariant, como se muestra en el ejemplo siguiente:

string message = FormattableString.Invariant($"Date and time in invariant culture: {DateTime.Now}");
Console.WriteLine(message);
// Output is similar to:
// Date and time in invariant culture: 05/17/2018 15:46:24

Conclusión

En este tutorial se han descrito escenarios habituales en los que se usa la interpolación de cadenas. Para más información sobre la interpolación de cadenas, vea el tema Interpolación de cadenas. Para más información sobre cómo aplicar formato a tipos .NET, vea los temas Aplicar formato a tipos en .NET y Formatos compuestos.

Vea también