1. Operador de fusión con null (??)
Tus conocimientos sobre los tipos nullable no estarán completos si no sabes escribir construcciones concisas y seguras. En C# tienes dos operadores súper útiles para esto: fusión con null (??) y el operador condicional null (?.).
El operador ?? te permite establecer un “valor por defecto” para una variable que puede ser null.
Imagina que tienes un nombre de usuario que puede ser null. Y si realmente es null, quieres mostrar "Invitado". Ejemplo:
string userName = null;
string displayName = userName != null ? userName : "Invitado";
El operador ?? te permite escribir esto de forma más compacta:
string userName = null;
string displayName = userName ?? "Invitado";
¿Cómo funciona?
- Si la expresión a la izquierda no es null, se devuelve como resultado.
- Si la izquierda es null, se usa el valor de la derecha.
Más ejemplos:
int? age = null;
int displayAge = age ?? -1; // -1 — valor por defecto
Console.WriteLine(displayAge); // Mostrará -1
string input = null;
string name = input ?? "Invitado";
Console.WriteLine($"Hola, {name}!"); // Hola, Invitado!
Cadenas de operadores
Puedes encadenar ??:
string result = str1 ?? str2 ?? "Por defecto";
Si str1 no es null, se usa. Si no, str2; si también es null, entonces la cadena "Por defecto".
2. Operador condicional null (?.)
Otra situación común: llamar a un método o acceder a una propiedad de un objeto solo si el objeto no es null. Ejemplo:
User user = null;
string displayName = user != null ? user.Name : null;
El operador ?. te permite escribir esto de forma más simple:
User user = null;
string displayName = user?.Name;
Si el objeto user es null, la expresión no lanzará error, simplemente devolverá null.
Ejemplos:
User user = null;
// Sin ?. — habrá error
// Console.WriteLine(user.Name); // NullReferenceException
Console.WriteLine(user?.Name); // Seguro — imprimirá cadena vacía o nada
Console.WriteLine(user?.GetProfileInfo()); // Igual
User[] users = null;
int? count = users?.Length; // null si users == null
Cadenas de operadores
Puedes construir cadenas completas:
string domain = company?.Director?.Email?.Split('@')?[1];
Si cualquier parte del camino resulta ser null, la expresión devolverá null en vez de lanzar una excepción.
Combinando con ??
Los operadores ?. y ?? funcionan genial juntos:
string display = user?.Name ?? "Desconocido";
Si user o user.Name son null, se mostrará "Desconocido".
3. ¿Qué es ! y para qué sirve?
Operador para suprimir advertencias sobre null
En las versiones modernas de C# (con NRT activado), el compilador te avisa si accedes a una variable que puede ser null. Pero a veces tú sabes que todo está bajo control. Entonces se usa el operador de supresión !.
string? possibleNull = GetUserNameMaybeNull();
Console.WriteLine(possibleNull.Length); // Warning: puede ser null
Console.WriteLine(possibleNull!.Length); // El compilador no dice nada, pero si es null — habrá excepción
Importante: ! no te protege de errores — solo le dice al compilador "confía en mí". Si la variable realmente es null, tendrás un NullReferenceException.
Cuándo no deberías usarlo
No uses ! a ciegas. Es buena práctica minimizar su uso. Mejor reestructura el código para que null sea imposible o esté claramente gestionado.
4. default — cómo obtener el valor "estándar" de un tipo
A veces solo quieres "resetear" una variable a su estado inicial, sobre todo si no quieres escribir a mano 0, false o null.
Para eso existe la palabra clave default.
int a = default; // a == 0
bool flag = default; // flag == false
string s = default; // s == null
double? d = default; // d == null
En tu mini-aplicación puedes, por ejemplo, resetear el nombre o la edad:
userName = default; // null
userAge = default; // null (si userAge es int?)
5. Diferencias y matices: ?, !, default
Incluso los desarrolladores con experiencia a veces se lían cuando ven ?, ! y default juntos. Vamos a aclarar quién es quién.
? — permites null
- Para tipos valor: int? x — ahora x puede ser null.
- Para tipos referencia: string? s — indicas explícitamente que la variable puede ser null (en modo NRT).
! — afirmas que null no ocurrirá
- user!.Name — le prometes al compilador que user seguro no es null.
- Solo funciona en modo Nullable Reference Types.
default — pides el valor "por defecto"
- int x = default; — x será 0
- string s = default; — s será null
Comparación:
| Sintaxis | ¿Qué es? | ¿Dónde funciona? | ¿Qué pasa con null? |
|---|---|---|---|
|
Tipo valor nullable | En todas partes | Puedes asignar null |
|
Tipo referencia nullable (NRT) | En modo NRT | Puedes asignar null |
|
Null-forgiving operator | En modo NRT | Suprime advertencia |
|
Valor por defecto | En todas partes | Para referencias — es null |
6. Errores típicos al usar ?, ! y default
Error nº1: creen que ! "cura" el null.
En realidad, ! solo hace que el compilador no se queje. Si el valor resulta ser null, la app se cae con NullReferenceException.
Error nº2: olvidan comprobar .HasValue antes de usar .Value.
Esto pasa sobre todo con int?, bool? y otros tipos nullable. Sin esa comprobación puedes tener una excepción InvalidOperationException.
Error nº3: usan default donde hace falta un "significado especial" de cero.
Por ejemplo, 0 o false pueden ser valores válidos, no señales de "vacío". Esto puede llevar a errores lógicos.
Error nº4: no usan ? para tipos referencia en modo NRT — o lo usan demasiado.
Algunos se olvidan del ? y el compilador suelta un montón de advertencias. Otros, al revés, ponen ? en todas partes, incluso donde null nunca va a estar. Ambas cosas hacen el código menos legible y fiable.
GO TO FULL VERSION