En noviembre de 2022 se lanzó .NET 7 y desde ese momento tenemos disponibles todas las novedades que trae C# 11. A continuación revisamos algunas de ellas.
Puedes encontrar el código fuente de los ejemplos en repositorio: https://github.com/fjvela/csharp-11
Raw strings
Hasta ahora la manera de poder definir cadenas de texto multilínea en C# es utilizar el prefijo @. Uno de los problemas que presenta es que si se indenta el texto la salida de este se verá afectada o si se utilizan comillas dobles es necesario escaparlas.
C# 11 incluirá una nueva manera de definir cadenas de texto, para ello deberemos utilizar como mínimo tres comillas """
. Esto nos facilitará poder indentar cadenas de texto en nuestro código y evitar tener que escapar las comillas. En el caso de utilizar una cadena de texto interpolada (string interpolation - “Hello, I’m {{ name }}”), deberemos utilizar como mínimo dos dólares $$
.
Definición de cadenas de texto multilínea en C#
var myString = @"
<element attr=""content""/>";
Resultado:
<element attr="content"/>
Definición de cadenas de texto multilíneas en C# 11
var myStringRaw = """
<element attr="content"/>
""";
Resultado:
<element attr="content"/>
Definición de cadenas de texto interpoladas en C# 11
var myJSONRawInterpolated = $$"""
{
"name": "{{name}}"
}
""";
Resultado:
{
"name": "Javi Vela"
}
Resultado binario decompilado
A continuación puedes ver el código decompilado:
List patterns
Nos permitirá comparar un patrón con un array o list de elementos, por lo que podríamos definir un método con los siguientes patrones:
int CheckSwitch(int[] values) => values switch
{
[1, 2, .., 10] => 1,
[1, 2] => 2,
[1, _] => 3,
[1, ..] => 4,
[21] => 5,
[21, _, ..] => 6,
[33, _, 34, .., 44] => 7,
[_, ..] => 50
};
Los resultados de la ejecución son:
Console.WriteLine(CheckSwitch(new[] { 1, 2, 10 })); // prints 1
Console.WriteLine(CheckSwitch(new[] { 1, 2, 7, 3, 3, 10 })); // prints 1
Console.WriteLine(CheckSwitch(new[] { 1, 2 })); // prints 2
Console.WriteLine(CheckSwitch(new[] { 1, 3 })); // prints 3
Console.WriteLine(CheckSwitch(new[] { 1, 3, 5 })); // prints 4
Console.WriteLine(CheckSwitch(new[] { 2, 5, 6, 7 })); // prints 50
Console.WriteLine(CheckSwitch(new[] { 21, 52, 63, 74, 5 })); // prints 5
Console.WriteLine(CheckSwitch(new[] { 21 })); // prints 6
Console.WriteLine(CheckSwitch(new[] { 33, 0, 34, 1, 2, 3, 44 })); // prints 7
También podemos utilizarlo con la sentencia if
y obtener los valores del mismo:
if (numbers is [var first, _, _])
{
Console.WriteLine($"The first element of a three-item list is {first}.");
}
if (numbers is [1, var second, _])
{
Console.WriteLine($"The second element of a three-item list is {second}.");
}
Resultado binario decompilado
A continuación puedes ver el código decompilado:
UTF-8 String literals
Si tu aplicación necesita cadenas de texto en formato UTF-8 (ej: necesita comunicarse con otras a través de protocolos HTTP), el sufijo u8
puede ahorrarte unas líneas de código.
Añadiendo el sufijo u8
, automáticamente transforma la cadena de texto en un array de bytes en formato UTF-8.
Por defecto para convertir una cadena de texto en un array de bytes en UTF-8, necesitas:
byte[] data = System.Text.Encoding.UTF8.GetBytes("Javi Vela");
Gracias al sufijo ‘u8’, simplificamos la conversión:
byte[] data = "Javi Vela"u8.ToArray();
Resultado binario decompilado
A continuación puedes ver el código decompilado:
Newlines in string interpolation expressions
Versiones anteriores C# 11 no permiten el uso de saltos de línea en cadenas de texto interpoladas (string interpolation - “Hello, I’m {{ name }}”).
En el caso de utilizarlas, el compilador da un error como podemos ver en la siguiente imagen.
C# 11 nos permite añadir saldos de línea sin modificar el formato del texto:
Console.WriteLine($"Hello {name
}!!, How are you?");
Resultado binario decompilado
A continuación puedes ver el código decompilado:
Generic math support
C# 11 incluye el soporte genérico de los datos matemáticos, permitiéndonos construir métodos genéricos como el siguiente:
T AddAll<T>(T[] items) where T : INumber<T>
{
T result = T.Zero;
foreach (var item in items)
result += item;
return result;
}
int[] numbers = new[] { 1, 5, 6, 9, 19};
Console.WriteLine(AddAll(numbers));
Required members
Existe un nuevo modificador required
que podemos añadir a nuestras propiedades para indicar que los constructores deben inicializar esa propiedad, en caso contrario nuestra aplicación no compilara.
El siguiente código muestra la inicialización de una clase pero no se ha inicializado la propiedad Name en el constructor por lo que tendremos un error de compilación.
var user = new User { };
Console.WriteLine($"Name: {user.Name}");
class User
{
public required string Name { get; init; }
}
File-local types
Se incluye en C# 11 un nuevo modificador de clases, file
. Al indicar el modificador de acceso file
estamos indicando que la visibilidad (scope) de la clase es dentro del mismo fichero.
Resultado binario decompilado
A continuación puedes ver el código decompilado:
Auto-default-structs
Versiones anteriores a C# 11 obligan a inicializar todas las propiedades de un struct. C# 11 inicializará automáticamente todas las propiedades que no han sido inicializadas.
En la siguiente imagen podemos ver como automáticamente se ha inicializado la propiedad ‘Y’ con el valor por defecto de su tipo, en este caso cero.
Resultado binario decompilado
A continuación podemos ver la librería decompilada y como el compilador ha añadido el código necesario para inicializar la propiedad por nosotros: