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 ;)

18 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, 21 de mayo de 2024
C#

Revisando código ajeno, me he encontrado con un ejemplo de uso del operador null coalescing assignment de C# que me ha parecido muy elegante y quería compartirlo con vosotros.

Como recordaréis, este operador, introducido en C# 8, es una fórmula muy concisa para asignar un valor a una variable si ésta previamente es null, una mezcla entre el operador de asignación y el null coalescing operator que disfrutamos desde C# 2:

// C# "clásico":
var x = GetSomething();
...
if(x == null) {
    x = GetSomethingElse();
}

// Usando null coalescing operator (C# 2)
var x = GetSomething();
...
x = x ?? GetSomethingElse();

// Usando null coalescing assignment (C# 8)
var x = GetSomething();
...
x ??= GetSomethingElse();

Pero, además, al igual que otras asignaciones, este operador retorna el valor asignado, lo que nos permite encadenar asignaciones y realizar operaciones adicionales en la misma línea.

Por ejemplo, observad el siguiente código:

Console.WriteLine(y ??= "Hello, World!");

Aquí, básicamente lo que hacemos es asignar el valor "Hello, World!" a la variable si ésta contiene un nulo, y luego imprimirlo por consola. Y si no es nulo, simplemente se imprime su valor actual.

El código que he me ha llamado la atención sigue más o menos esa línea, y se trataba de un método que debía obtener un valor desde un origen de datos y dejarlo cacheado para llamadas posteriores al mismo. En C# "de toda la vida", más o menos podría ser algo así:

public class MyClass
{
    private string _cachedValue;
    ...
    public async Task<string> GetValueAsync() 
    {
        if(_cachedValue == null) 
        {
            _cachedValue = await GetValueFromSlowStorageAsync();
        }
        return _cachedValue;
    }
}    

La implementación que me ha parecido muy concisa y elegante es la siguiente:

public class MyClass
{
    private string _cachedValue;
    ...
    public async Task<string> GetValueAsync() 
            => _cachedValue ??= await GetValueFromSlowStorageAsync();
}

En una única expresión estamos consiguiendo:

  1. Si el valor estaba previamente cacheado, lo retornamos sin hacer nada más.
  2. En caso contrario, lo obtenemos desde la fuente de datos y lo almacenamos en la variable _cachedValue, de forma que llamadas posteriores retornarán el valor cacheado.
  3. Finalmente, retornamos el valor recién obtenido para que el cliente del método lo reciba.

Bonito, ¿verdad?

Publicado en Variable not found.

2 Comentarios:

Albert Capdevila dijo...

Sí que lo es :)

He utilizado mucho el:
var x = GetSomething() ?? GetSomethingElse();

Éste en cambio nunca lo he utilizado. Lo guardo en la caja de herramientas.

¡Gracias!

José María Aguilar dijo...

Hola!

Sí, es que parece que el null coalescing operator "??" lo tenemos en general bastante más interiorizado que la asignación "??=". Creo que estos ejemplos están bien para ver usos prácticos que nos permitan recordarlos con más facilidad y usarlos cuando encajen :)

Muchas gracias por comentar!