En el mundo de la programación, especialmente con lenguajes como C#, es común encontrarse con situaciones donde una variable o un objeto puede no tener un valor asignado. Para abordar esta realidad, C# introduce los tipos que aceptan valores nulos, una extensión que permite a los tipos de valor contener el valor null además de sus valores normales.
Los tipos nullables en C# son una extensión de los tipos de valor que permite que puedan contener el valor null (además de sus valores normales). Esto es útil en escenarios donde un valor puede ser opcional o no siempre está disponible. En C#, el valor null se utiliza para representar una ausencia de valor.
Sin embargo, los tipos de valor (como int, double, bool) no pueden ser null por defecto, siempre tienen un valor predeterminado. Para abordar esta limitación, C# introduce los tipos nullables, que permiten que los tipos de valor puedan tener el valor null.
Normalmente, use un tipo de valor que acepta valores NULL cuando necesite representar el valor indefinido de un tipo de valor subyacente. Por ejemplo, una variable booleana, o bool, solo puede ser true o false. Sin embargo, en algunas aplicaciones, un valor de variable puede estar sin definir o faltar. Por ejemplo, un campo de base de datos puede contener true o false, o puede que no contenga ningún valor, es decir, NULL.
Un tipo de valor que admite un valor NULL T? representa todos los valores de su tipo de valor subyacente T y un valor NULL adicional. Por ejemplo, puede asignar cualquiera de los tres valores siguientes a una variable bool?: true, false o null. El valor predeterminado de un tipo de valor que acepta valores NULL representa null.
Lea también: IVA 21% Excel
Declaración de Tipos Nulos
Para declarar un tipo nullable, se usa el operador ? después del tipo de valor. Por ejemplo, int? es un tipo nullable que puede contener un entero o null. La sintaxis para declarar un tipo nullable es simple:
int? numero;
Aquí, numero es una variable que puede contener un entero o el valor null. También se puede asignar el valor null.
Bajo el capó, la sintaxis anterior utiliza la estructura genérica System.Nullable<T>. Todos los tipos que admiten valores NULL son instancias de la estructura System.Nullable<T> genérica. Ambas formas (Nullable<T> y T?) son equivalentes, pero el uso del operador ? es más común y más sencillo de leer.
Dado que un tipo de valor se puede convertir implícitamente en el tipo de valor que acepta valores NULL correspondiente, puede asignar un valor a una variable de un tipo de valor que acepta valores NULL tal como lo hace para su tipo de valor subyacente. Un tipo de valor que no admite valores NULL T se convierte implícitamente al tipo que admite valores NULL T?.
Comprobación de Nulidad
Cuando trabajas con el lenguaje de programación C#, es probable que te encuentres con situaciones donde necesitas verificar si una variable u objeto es nulo. Para verificar si un tipo nullable tiene un valor o es nulo, puedes usar las propiedades HasValue y Value.
Lea también: Guía IVA reducido
- La propiedad HasValue indica si el tipo nullable contiene un valor.
- Nullable<T>.Value obtiene el valor de un tipo subyacente si HasValue es true.
Además de estas propiedades, C# ofrece dos enfoques comunes para comprobar la nulidad: == null y is null. Vamos a explorar cada uno de ellos para entender sus diferencias y cuándo usarlos.
1. == null: Comparación de Igualdad con Null
El operador == se utiliza para comparar valores en C#. Cuando lo aplicas con null, estás verificando si la variable o el objeto tiene una referencia nula.
string str1 = null;string str2 = "Hola";if (str1 == null){ // str1 es nulo}if (str2 == null){ // str2 no es nulo}En este caso, la primera condición str1 == null se evalúa como verdadera porque str1 es nulo. En cambio, la segunda condición str2 == null es falsa, ya que str2 contiene la cadena “Hola” y no es nulo.
Este enfoque es útil para:
- Verificar si una variable tiene una referencia nula.
- Evaluar si un objeto o variable no ha sido inicializado o asignado.
2. is null: Verificación de Nulidad con el Operador is
El operador is se utiliza para comprobar si un objeto es de un tipo específico. Cuando se combina con null, se utiliza para verificar si el objeto es nulo.
Lea también: ¿Cómo localizar tus XML del SAT?
string str1 = null;string str2 = "Hola";if (str1 is null){ // str1 es nulo}if (str2 is null){ // str2 no es nulo}En este ejemplo, str1 is null se evalúa como verdadero porque str1 es nulo. Por otro lado, str2 is null es falso porque str2 contiene una cadena y no es nulo.
Este enfoque es útil para:
- Realizar una verificación concisa de nulidad.
- En situaciones donde deseas expresar de manera clara que estás comprobando si un objeto es nulo.
Ambos enfoques son válidos, y la elección entre == null y is null a menudo dependerá del contexto y de tus preferencias personales. La claridad y la legibilidad del código son esenciales, especialmente cuando estás comenzando en la programación. Recuerda que el objetivo es escribir código comprensible para ti y para otros desarrolladores.
Manejo de Valores Nulos con el Operador de Coalescencia Nula (??)
En nuestro día a día como programadores, nos encontramos de esas situaciones en las que tenemos que validar si una variable es nula y, si lo es, asignarle un valor por defecto. El operador de coalescencia nula (??) es un operador de C# que permite asignar un valor predeterminado a una variable si su valor actual es nulo. Este operador proporciona una forma compacta de manejar los valores nullables, permitiendo definir un valor predeterminado en caso de que el nullable sea null.
Si desea asignar un valor de un tipo de valor que acepta valores NULL a una variable de tipo de valor que no acepta valores NULL, es posible que tenga que especificar el valor que se va a asignar en lugar de null. Use el operador ?? de fusión null para hacerlo.
int? a = null;int b = a ?? 10; // Si 'a' es null, 'b' será 10. Si 'a' tiene un valor, 'b' será ese valor.double? precioProducto = null;double precioMostrar = precioProducto ?? 0.0; // precioMostrar será 0.0string nombreUsuario = null;string mensaje = nombreUsuario ?? "Invitado"; // mensaje será "Invitado"string mensajeBienvenida = "Bienvenido!";string mensajeMostrar = mensajeBienvenida ?? "Hola"; // mensajeMostrar será "Bienvenido!"// Ejemplo con un objeto// Se asume la existencia de una clase Usuario y un método ObtenerUsuario()// Usuario usuario = ObtenerUsuario() ?? new Usuario("Invitado");// Si ObtenerUsuario() devuelve null, se crea un nuevo objeto Usuario.En el ejemplo anterior con int? numero, si numero es null, resultado tomará el valor 5. ¡Un cambio radical verdad? Si nombreUsuario no es nulo, ¡tendrás su nombre!
También debes haber enfrentado el desafío de las excepciones cuando intentas acceder a un objeto nulo. Aquí nuevamente, el operador ?? puede ser de gran ayuda para prevenir NullReferenceException.
Operadores con Tipos Nulos (Operadores Elevados)
Un tipo T? de valor que acepta valores NULL admite los operadores unarios y binarios predefinidos o los operadores sobrecargados que admite un tipo T de valor. Estos operadores, también conocidos como operadores de elevación, devuelven null si uno o ambos operandos son null. De lo contrario, el operador usa los valores contenidos de sus operandos para calcular el resultado.
Operadores de Comparación
Para los operadores de comparación (<, >, <= y >=), si uno o ambos operandos son null, el resultado es false. De lo contrario, se comparan los valores contenidos de los operandos. Es importante no suponer que, dado que una comparación determinada (por ejemplo, <=) devuelve false, la comparación opuesta (>) devuelve true.
Operadores de Igualdad y Desigualdad
- Para el operador == de igualdad, si ambos operandos son null, el resultado es true. Si solo uno de los operandos es null, el resultado es false.
- Para el operador != de desigualdad, si ambos operandos son null, el resultado es false. Si solo uno de los operandos es null, el resultado es true.
Consideraciones y Mejores Prácticas
Limita lo máximo posible el uso del valor null en tu código, porque tiene múltiples consecuencias negativas en la mantenibilidad del mismo. Por lo tanto, limita también al máximo la cantidad de objetos nullables, es decir, que pueden tener un valor nulo.
El valor nulo (null) es un valor especial que se utiliza para indicar justamente que no hay valor. Cuando un objeto es null e intentamos acceder a uno de sus campos, se produce una excepción en tiempo de ejecución, ya que no es posible hacerlo y el programa no tiene ninguna opción para continuar. Esto es lo que se conoce como NullReferenceException, y ahí se para en seco la ejecución del programa, ninguna de las instrucciones que siguen se van a ejecutar jamás.
Ante la incertidumbre de que el valor del objeto sea nulo, nos volvemos defensivos añadiendo comprobaciones condicionales para evitar estas excepciones no controladas. Esta programación defensiva tiene un efecto dominó o burbuja, que hace que en las demás capas del código volvamos a añadir comprobaciones para evitar acceso a nulos. Es fácil terminar llenando el código de comprobaciones sobre los nulos por todas partes, repitiendo la misma lógica de control en multitud de artefactos del sistema.
Lo mejor para minimizar los nulos es evitar que se generen y si no, al menos evitar su propagación.
