
El operador "?." (también conocido como safe navigation operator, null-conditional operator, optional chaining operator o incluso Elvis operator) se introdujo en C# 6.0, en el año 2015. Este conocido operador simplifica el acceso a miembros de un objeto que ocasionalmente podría ser nulo, evitando la necesidad de realizar comprobaciones explícitas de nulidad.
var friend = GetFriendOrNull(1);
var name = friend?.Name; // Si friend es nulo, name será nulo, pero no explotará
Sin embargo, si queremos acceder a una propiedad para asignarle un valor, el operador "?." no es suficiente. Por ejemplo, si queremos asignar un valor a la propiedad Age
de un objeto friend
sospechoso de ser nulo, debemos comprobarlo manualmente antes de realizar la asignación:
var friend = GetFriendOrNull(1);
if (friend != null)
{
friend.Age = 23;
}
Esto cambiará con C# 14, cuyo lanzamiento está previsto para noviembre de 2025, acompañando a .NET 10, que extenderá el uso de este operador también a la asignación de valores a miembros, completando así su funcionalidad.
Se trata de una característica muy esperada por la comunidad desde hace años, ya que simplificará y hará el código más legible. En este artículo, exploraremos cómo funcionará esta nueva característica y qué implicaciones tendrá en nuestro código.
Null-conditional assignment
La nueva versión de C# permitirá utilizar el operador "?." en el lado izquierdo de una asignación, lo que significa que se podrá asignar un valor a un miembro de un objeto sólo si dicho objeto no es nulo. En caso contrario, la asignación no se llevará a cabo y no se producirá una excepción de referencia nula.
Para que podáis comprender la utilidad rápidamente, veamos un ejemplo simple:
var friend = GetFriendOrNull(1);
friend?.Name = "John Doe"; // Si friend es nulo, no se lanza excepción y no se asigna valor
// Esto sería el equivalente a:
var friend = GetFriendOrNull(1);
if (friend != null)
{
friend.Name = "John Doe";
}
El mismo concepto puede extenderse a cualquier tipo de asignación de valores, incluso arrays y eventos:
var colors = GetColorsArrayOrNull();
colors?[0] = "Black"; // Si colors es nulo, no se lanza excepción y no se asigna valor
var button = GetButtonOrNull("btn1");
button?.Click += Handler; // No se lanza excepción aunque button sea nulo
button?.Click -= Handler; // No se lanza excepción aunque button sea nulo
Más detalles importantes
Internamente, el compilador de C# evalúa en primer lugar el lado izquierdo de la asignación. Si no es nulo, evalúa el lado derecho y realiza la asignación. Si el lado izquierdo es nulo, simplemente se ignora la asignación:
var friend = GetFriendOrNull(1);
friend?.FavoriteNumber = SumFirstPrimes(1000); // no ejecuta SumFirstPrimes() si friend es nulo
int id = 1;
friend?.Id = id++; // Si friend es nulo, id no se incrementará
Otra particularidad de este operador es que no podremos utilizarlo si estamos realizando asignaciones mediante tuplas y deconstrucción. Es decir, el siguiente código generará un error de compilación:
var friend = GetFriendOrNull(1);
(friend?.Name, friend?.Age) = ("John", 34); // Error de compilación
Tampoco está permitido utilizarlo con autoincrementos o autodecrementos:
var friend = GetFriendOrNull(1);
friend?.Age++; // Error de compilación
friend?.Age--; // Error de compilación
¿Cómo probarlo hoy?
Actualmente, C# 14 es todavía una versión preliminar y no está disponible en la versión estable de .NET y Visual Studio. Sin embargo, ya se puede probar en las previews recientes de .NET 10, que incluyen el compilador de C# 14 con las características implementadas hasta la fecha.
Los que queráis echar un vistazo, simplemente debéis descargar la última preview de .NET 10 y C# 14 desde el sitio oficial de Microsoft y probarlo en vuestros proyectos usando Visual Studio Preview, VS Code o lo que queráis. Eso sí, tendréis que crear un proyecto .NET 10 y habilitar la versión previa del lenguaje insertando las siguientes líneas en el archivo de proyecto:
<Project Sdk="Microsoft.NET.Sdk">
...
<PropertyGroup>
<LangVersion>preview</LangVersion>
</PropertyGroup>
</Project>
Con la llegada de C# 14, podremos disfrutar de esta nueva funcionalidad que nos permitirá realizar asignaciones condicionales de manera más eficiente y elegante.
Publicado en Variable not found.
7 Comentarios:
Por primera vez, estoy en contrísima de una nueva característica del sisharp. Pero muy en contra. Eso puede llegar a generar unos bugardos muy oscuros de descubrir para el que no tenga claro que una variable pueda ser nula o no...
"Por primera vez"... venga hombre, seguro que alguna otra protesta habrás levantado 😄😄
Yo no lo veo mal. En realidad, lo que está mal es que tengas referencias puedan que (o no) ser nulas, y eso es algo que a día de hoy puedes controlar de forma relativamente sencilla con las características de nulabilidad en tipos valor y referencia y usando algunos patrones.
Ahora bien, una vez que estás trabajando en un escenario en el que puede darse ese caso, al final se trata sólo de un azucarillo sintáctico, un relajante muscular para nuestros dedos. Al final, implementarás la misma lógica a base de "ifs", sólo que aquí lo harás tecleando menos.
Muchas gracias por comentar!
¿Protestar yo? ¿Dónde habrás visto tu eso? :-P
(Poco he protestado con la gañanada de objeto-valor y objeto-referencia, la mutabilidad de algo que hereda de un objeto-referencia-by-design y que "mágicamente" se transforma en un objeto-valor porque sí, porque el Heljsberg no pensó que los tipos nativos siendo objetos puros tendrían el rendimiento en el c*lo).
Siempre tan comedido 😄😄😄😄
Soy todo un dechado de humildad, paciencia, belleza y amabilidad. 😁😁😁😁🤣🤣
Este código del artículo dará error de compilación, pero por otro motivo ("f" no existe):
var friend = GetFriendOrNull(1);
(f?.Name, f?.Age) = ("John", 34); // Error de compilación
Cagonlamar, dónde estarán los compiladores cuando se necesitan 😄
Gracias por apuntarlo, Carlos!
Enviar un nuevo comentario