Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

17 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 5 de mayo de 2015
C# 6Ya jugando con Visual Studio 2015 y C# 6, estoy comprobando que la interpolación de cadenas es una de las características más interesantes y prácticas de las novedades que presentará la nueva versión del lenguaje, porque no son pocas las ocasiones en las que creamos expresiones concatenando literales de cadena y variables, o que hacemos uso de String.Format() para construir strings más complejos.

Hace unos meses ya adelantamos por aquí sus principales características, aunque aún era algo pronto para poder probar en profundidad esta nueva y esperada feature. Ahora, más avanzado ya su desarrollo, ha llegado el momento de echarle otro vistazo más en profundidad y ver cómo queda finalmente (o casi finalmente, todavía podría cambiar algo!).

En este post vamos a ver rápidamente los puntos principales a tener en cuenta para dominar esta nueva característica que sin duda facilitará nuestro trabajo y nos hará más productivos.

1. Interpolación de cadenas a vista de pájaro

Consiste en introducir valores de variables o expresiones en el interior de cadenas de texto sin usar los tradicionales mecanismos, molestos y propensos a errores, como la concatenación o el formateo con String.Format().

Y como un poco de código vale más que mil palabras, he ahí un ejemplo que creo ilustra bastante bien de qué estamos hablando:

Interpolated strings at a glance

Las cadenas interpoladas comienzan con el prefijo “$”, y pueden aparecer en los mismos lugares que una cadena de caracteres tradicional. Es decir, donde siempre hemos podido introducir una cadena de texto, podremos introducir ahora la nueva construcción $"something".

2. Parámetros en cadenas interpoladas

Cuando el compilador de C# encuentra una cadena precedida por el símbolo “$” entenderá que es una cadena con interpolación, y creará el string resultante sustituyendo las expresiones contenidas entre llaves por su valor evaluado en el ámbito local.

Por ejemplo, en la siguiente porción de código se muestra el uso correcto de la variable local name y de la propiedad estática LastName, mientras que la propiedad age no puede referenciarse desde el método estático Main() por ser un miembro de instancia:

Interpolation parameters must be in scope

Si queremos introducir los caracteres de apertura o cierre de llaves en alguna de estas cadenas, debemos escaparlos introduciéndolos dos veces consecutivas:

Curly braces must be scaped

3. Intellisense, refactorings y errores en compilación

Visual Studio nos ayudará durante la codificación de estas cadenas gracias al soporte completo de intellisense en el interior de las expresiones interpoladas:

Intellisense in string interpolation

También estos parámetros en el interior de las cadenas de texto serán sensibles a refactorizaciones. Por ejemplo, si en el código anterior renombramos la variable name a fullName, el nuevo nombre será introducido también automáticamente en el interior de la cadena:

Interpolated string parameters support refactorings
Y por supuesto, cualquier error a la hora de codificar las expresiones se nos notificará en tiempo de compilación, evitando así problemas posteriores, e incluso Visual Studio nos propondrá posibles soluciones para corregirlo:

Compilation errors in string interpolation

4. Expresiones como parámetros

Aunque la forma habitual de uso será probablemente utilizar directamente variables o propiedades como parámetros en las cadenas interpoladas, en realidad entre la apertura y cierre de las llaves podemos poner cualquier expresión que evalúe a object. En la práctica, cualquier expresión no void valdrá:

Expressions in string interpolation

Por supuesto, podemos incluir todo tipo de expresiones, aunque a veces será necesario el uso de paréntesis:

Complex parameters in interpolated strings

La única condición es que la expresión sea válida y compilable en el punto exacto en el que se produce la interpolación. Si la expresión contiene términos definidos en espacios de nombre distintos al actual, o bien se cualifican por completo o bien se insertan los using necesarios en el archivo de código fuente en el que se encuentra la expresión.

5. Los parámetros pueden ser formateados

Al igual que ocurre en el clásico String.Format(), podemos incluir información de formato en los parámetros que incluimos en las cadenas interpoladas con una sintaxis bastante predecible: simplemente, tras la expresión a evaluar, incluimos el carácter dos puntos “:” y a continuación la cadena de formato que especifica cómo debe presentarse la información.

Las cadenas de formato son las estándar en .NET, las que hemos usado toda la vida en String.Format(). Veamos unos ejemplos:

Standard formatting strings

Opcionalmente podemos indicar también el número de caracteres del resultado insertando antes de la especificación el número separado por una coma, y la alineación del contenido (derecha positivo, izquierda negativo):

Formatting and padding in C# string interpolation

6. Los parámetros pueden ser objetos IFormattable

Si parámetros introducidos en una cadena interpolada son objetos IFormattable, se invocará a su método ToString() para que sea él mismo el que se formatee:

Interpolated strings with IFormattable parameters

7. La cultura por defecto es la del hilo actual

Si vamos a utilizar formateo, este detalle es importante: la cultura aplicable será la activa en el hilo de ejecución actual.

String interpolation culture in C#

Esto tiene bastante sentido porque este comportamiento es consistente con su equivalente utilizando String.Format().

8. Las cadenas interpoladas actúan como strings

En los ejemplos que hemos visto hasta ahora, las cadenas interpoladas eran meros sustitutos de un string clásico. El compilador de C# detecta este escenario y durante el proceso de compilación son transformadas en una llamada al método string.Format() como podemos observar en el siguiente código:

Interpolated strings are just strings

Por cierto, si queréis ver cómo funciona esta transformación por dentro, podéis hacer pruebas en la dirección http://tryroslyn.azurewebsites.net/, un sitio web powered by Roslyn en el que podréis introducir código C# 6.0 y ver el resultado descompilado. Muy interesante y recomendable :)

9. Las cadenas interpoladas también actúan como objetos IFormattable

Si el compilador detecta que estamos usando una cadena interpolada en lugar de un objeto IFormattable, actuará de forma ligeramente diferente, lo que nos da alguna ventaja si queremos intervenir en el proceso de formateo de estas cadenas.

Fijaos en este código, donde pasamos la cadena interpolada a una función cuyo parámetro se espera que sea IFormattable:

Interpolated strings as IFormattable objects

En este caso, el código equivalente generado por Roslyn será el siguiente. Se puede observar que no ha sido transformado en una llamada a String.Format() sino en una invocación a FormattableStringFactory.Create(), que construirá el objeto IFormattable que espera la función ToUpper() vista anteriormente.

Interpolated strings as IFormattable objects

¿Y por qué es interesante esto? Pues porque esta técnica nos permite crear formateadores personalizados de forma relativamente sencilla.

Por ejemplo, podemos usar esta capacidad para crear funciones que nos ayuden a formatear una cadena en una cultura determinada. El siguiente código, un clásico entre los ejemplos de uso de esta característica, muestra cómo podemos usar una función para formatear usando cultura invariante:

Format using invariant culture

Otros ejemplos muy ingeniosos que he visto consisten en utilizar esta característica para construir cadenas que requieren un tratamiento especial, como puede ser la construcción de una URL, o incluso una sentencia SQL. En ambos casos es interesante “retocar” el proceso de formateo de parámetros, en el primer caso para introducir codificación, y en el segundo para evitar efectos no deseados como inyecciones de script. No dejéis de echar un vistazo al blog de Thomas Levesque para verlos.

10. ¡Soporte para Heredoc!

En el primer vistazo que dimos a la interpolación de cadenas en C# 6 ya comenté que no había visto soporte para Heredoc o cadenas verbatim, un escenario en el que esta característica tenía mucha aplicación. Bien, pues esto parece que por fin ha cambiado, y ahora sí que podemos ya implementar cadenas interpoladas con múltiples líneas de texto.

Simplemente tenemos que insertar el carácter $ que caracteriza a las cadenas interpoladas justo antes de la arroba @ que indica el comienzo de la cadena verbatim:

Heredoc & interpolated strings

11. Sólo es syntactic sugar, aplicable en tiempo de compilación

Es importante tener en cuenta que esta característica es principalmente lo que solemos denominar syntactic sugar, es decir, una ayuda sintáctica destinada a endulzar la vida del desarrollador, por lo que se resuelve en tiempo de compilación, antes de ejecutar la aplicación.

No existe, por tanto, ningún tipo de penalización del rendimiento en runtime por usar esta técnica más allá del que encontraríamos al utilizar String.Format().

12. ¿Uso en versiones del framework anteriores a la 4.6?

Si usamos cadenas interpoladas como puros string, comentado en el punto 8 de este post, no tendremos problemas en usar esta característica. Es decir, podremos compilar sin problema nuestra aplicación usando C# 6 aunque el target del proyecto sea un .NET framework anterior al 4.6 y todo funcionará bien.

Sin embargo, sí tendremos problemas cuando tratamos cadenas interpoladas como IFormattable, y la explicación la tenéis un poco más atrás, en un sutil detalle que hemos deslizado cuando hablábamos del tratamiento de cadenas interpoladas como objetos IFormattable. Como decíamos, éstas se transformaban en una llamada a FormattableStringFactory.Create(), lo que obviamente implica que el compilador está asumiendo que esta clase existe, cuando en realidad esto no es así en las versiones anteriores a la 4.6 del framework.

En estos casos, la solución consiste únicamente en crear en el proyecto actual las clases FormattableStringFactory y FormattableString, cuyo código fuente podemos obtener desde Github mediante los enlaces anteriores. Y para los perezosos, existe un paquete Nuget (no oficial) que lo hace, y que podemos instalar así:

PM> Install-Package StringInterpolationBridge

Bueno, y es todo, creo ;) Espero que esta revisión en profundidad de la interpolación de cadenas os sea útil para conocer un poco mejor en qué consisten y cómo podrán ayudarnos en nuestro día a día cuando comencemos a trabajar con C# 6.

Publicado en Variable not found.

2 Comentarios:

Carlos Díez dijo...

Muy interesante como siempre, aprovecho para felicitarte por los 9 años del blog. Un saludo.

josé M. Aguilar dijo...

Muchas gracias, Carlos!