Me da la impresión de que el operador with
de C# no es demasiado conocido, y creo que vale la pena echarle un vistazo porque puede resultarnos útil en nuestro día a día.
Introducido con C# 9, allá por 2020, las expresiones with
proporcionan una forma sencilla de crear nuevas instancias de objetos "copiando" las propiedades de otro objeto, pero con la posibilidad de modificar algunas de ellas sobre la marcha. Esto, aunque puede usarse con varios tipos de objeto, es especialmente interesante cuando estamos trabajando con componentes inmutables, como son los records
, porque la única posibilidad que tenemos de alterarlos es creando copias con las modificaciones que necesitemos.
Parece que uno de los objetivos de C#10 es eliminar código de los archivos de código fuente de C#, simplificando su codificación y lectura. Lo hemos visto con la introducción de características como directivas using
globales o los using
implícitos: en ambos casos se ahorraba espacio en vertical sustituyendo los using
declarados individualmente en cada archivo por directivas aplicadas de forma global al proyecto, bien de forma explícita o implícita.
En cambio, los espacios de nombre con ámbito de archivo o namespace declarations permiten ahorrar espacio en horizontal, evitando un nivel de indentación en el código que la mayoría de las veces es innecesario.
Cuando aparece una nueva versión de C# o .NET, los titulares de las noticias, tweets y posts suelen girar en torno a las novedades más destacadas, aquellas que suponen cambios importantes respecto a versiones anteriores. Pero es habitual que, aparte de éstas, se añadan otras características más pequeñas que muchas veces pasan desapercibidas.
Esto es lo que ocurre con al atributo [CallerArgumentExpression]
, una joyita de C#10 que puede ayudarnos a hacer más descriptivos los mensajes de error y trazas que guardamos cuando aparece un error en nuestras aplicaciones.
Hace unos días hablábamos de las directivas using
globales, un interesante añadido a C# 10 que permite importar espacios de nombres en todos los archivos de código del proyecto, sin necesidad de repetir cientos de veces las mismas líneas en sus encabezados. Simplemente, si un namespace es interesante para nuestro proyecto, lo declaramos como global en algún punto y será lo mismo que si lo hubiéramos hecho en cada uno de los archivos .cs:
global using System;
global using System.Text;
global using System.Text.Json;
global using MyProject.Model;
...
Bien podían haberlo dejado aquí porque ya es una mejora sustancial respecto a lo que tenemos, pero no, el equipo de diseño de C# sigue introduciendo detalles que pueden hacernos la vida más sencilla. Es el caso de los implicit usings que, de la misma forma, acompañan a .NET 6 y C# 10.
Seguro que estáis acostumbrados a ver y escribir las, a veces extensas, listas de directivas using
encabezando vuestros archivos de código fuente C#. Aunque ciertamente los entornos de desarrollo actuales son de bastante ayuda a la hora de introducirlos e incluso a veces nos permiten colapsarlos, son unos grandes consumidores del valioso espacio vertical de nuestros monitores:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// ... (muchos using más)
namespace MyApplication
{
public class MyClass
{
...
}
}
Pero si habéis trabajado con Razor, ya sea para crear vistas MVC/Razor Pages o bien desde Blazor, seguro que os habrán encantado los archivos tipo _ViewImports.cshtml
o _Imports.razor
, pues permiten introducir directivas que se apliquen a todos los archivos Razor del proyecto.
¿No sería buena idea llevar esto mismo a nivel del lenguaje?