Dos signos de interrogación en C#: no es un error, sino una herramienta poderosa
\n\nImagina: estás escribiendo código en C# y de repente ves la construcción ??. El primer pensamiento: ¿un error tipográfico? ¿Un signo de más? En realidad, es uno de los operadores más elegantes y útiles del lenguaje: el operador de unión nula (null-coalescing operator). Si alguna vez te has topado con un NullReferenceException y has maldecido todo a tu alrededor, este operador será tu salvavidas.
En este artículo, analizaremos qué significan dos signos de interrogación en C#, cómo usarlos correctamente, en qué se diferencian del operador ternario y mostraremos ejemplos reales de la práctica. ¡Allá vamos!
\n\n¿Qué es el operador ?? en C#?
\n\nEl operador ?? (dos signos de interrogación) es un operador binario que devuelve el operando izquierdo si no es null; de lo contrario, devuelve el operando derecho. En pocas palabras: "Si lo de la izquierda no es null, toma lo de la izquierda; si no, toma lo de la derecha".
La sintaxis es extremadamente simple:
\n\nvar result = left ?? right;\n\nDonde:
\n- \n
left— el valor que puede ser null; \n right— el valor por defecto (no puede ser null si el tipo de la derecha es nullable). \n
Primer ejemplo: salvándonos de null
\n\nSupongamos que tienes una variable string? name (cadena nullable). Quieres mostrar el nombre del usuario y, si no tiene, "Invitado":
string? name = GetUserName(); // puede devolver null\nstring displayName = name ?? "Invitado";\nConsole.WriteLine(displayName);\n\nSin el operador ??, tendrías que escribir:
string displayName = (name != null) ? name : "Invitado";\n\n¿Estás de acuerdo en que la primera opción se lee como una frase normal: "nombre o invitado"? Bonito, ¿verdad?
\n\nOperador ??=: la nueva generación de unión nula
\n\nA partir de C# 8.0, apareció el operador ??=: una forma abreviada de asignación con unión nula. Asigna el valor del operando derecho al izquierdo solo si el operando izquierdo es null.
Sintaxis:
\n\nleft ??= right;\n\nEsto es equivalente a:
\n\nif (left == null) left = right;\n\nEjemplo con ??=
\n\nList<int>? numbers = null;\nnumbers ??= new List<int>(); // numbers ahora = new List<int>()\nnumbers.Add(42);\nConsole.WriteLine(numbers.Count); // 1\n\nObserva: si numbers ya estuviera inicializado (no null), no se produciría la asignación. Esto es ideal para la inicialización diferida.
Comparación con el operador ternario (? :)
\n\nMuchos principiantes confunden ?? con el operador ternario ? :. Aclaremos esto de una vez por todas:
- \n
- Operador ternario — es una forma abreviada de if-else. Verifica CUALQUIER condición booleana:
condición ? valor_si_true : valor_si_false. \n - Operador ?? — verifica SOLO si es null. Es un caso particular, diseñado para una tarea específica. \n
Ejemplo del operador ternario:
\n\nint age = 18;\nstring status = (age >= 18) ? "Adulto" : "Menor de edad";\n\nY esto es lo que sucede si intentas reemplazar ?? con el ternario:
string? name = null;\nstring displayName = name != null ? name : "Invitado"; // funciona, pero es más largo\nstring displayName2 = name ?? "Invitado"; // más corto y claro\n\nConclusión: usa ?? cuando solo necesites sustituir un valor por defecto en lugar de null. Para todas las demás condiciones, usa el operador ternario.
Cadena de operadores ??
\n\nPuedes encadenar varios operadores ?? en una secuencia. Esto es útil cuando hay varias fuentes posibles de un valor:
string? firstChoice = GetFromCache