El problema es lo fácil que es usar referencias nulas. Estos son los valores por defecto en C# para cada tipo de referencia. El dilema se responde con estas preguntas:
- ¿Qué más podría ser el valor por defecto?
- ¿Qué otro valor sería el más adecuado hasta que se decida? ¿Qué otro valor podría usarse para inicializar un array o referencias hasta que se llene con valores reales?
El problema, o al menos parte de él, se debe a que la C# no permite expresar si un nulo como valor en un contexto específico es bueno o malo.
¿Qué puedes hacer?
- Intención expresa
- Comportamiento de la fuerza
- Evitar la desreferenciación de los nulos
- Evitar los nulos
Estamos usando tipos anulables cuando necesitamos representar un valor indefinido de un tipo subyacente. Mientras que los valores booleanos pueden tener valores verdaderos o falsos, un nulo en este caso significa falso ya que no hay ningún valor indefinido. Cuando se tiene una interacción con la base de datos, un valor de variable puede ser indefinido o faltante. Un campo de una base de datos puede contener valores verdaderos, falsos o ningún valor. En este caso, un nullable de tipo bool es el camino a seguir.
Algunas cosas que hay que tener en cuenta cuando se trabaja con tipos nulos:
- Este tipo representa variables de tipo valor a las que se puede asignar el valor nulo.
- La T? es la sintaxis abreviada de Nullable< T
- Asigne un valor a un tipo nulo como lo haría con otros tipos int? = nulo o doble? = 10.0.
- Las propiedades de sólo lectura HasValue y Value pueden ser usadas para comprobar y obtener el valor de tal tipo.
- == y != los operadores pueden ser usados con un tipo nulo.
- Puedes usar la concordancia de patrones desde la versión 7.0 de C#.
- El valor por defecto de T? es un caso en el que HasValue evalúa a falso.
- El operador ?? – operador de coalescencia nula – permite asignar un valor al tipo subyacente basado en el valor del tipo nulo.
Declaremos algunos tipos anulables.
123456789101112131415161718192021 usando el sistema;namespace nllables{classProgram{staticvoidMain(string[] args){doble? nullableDouble =9.99;int? nullableInt =null;double standardDouble =19.19; Console.WriteLine($"La variable :: {nombrede(nullableDoble)} tiene valor :: {nullableDoble} y tiene valor evalúa a :: {nullableDoble.tiene valor}.");if(nullableInt.tiene valor){ Console.WriteLine($"La variable :: {nombrede(nullableInt)} tiene valor :: {nullableInt.Value} y HasValue evalúa a :: {nullableInt.HasValue}");}else{ Console.WriteLine($"La variable :: {nombrede(nullableInt)} no tiene valor!");} Console.WriteLine($"La variable ::: {nombrede(estandarDoble)} tiene valor :: {standardDoble}."); Console.ReadKey();}}
csharp
Esto nos da el siguiente resultado:
123La variable :: nullableDouble tiene valor :: 9.99 y HasValue evalúa a :: Verdad. La variable :: nullableInt no tiene valor! La variable :: standardDouble tiene valor :: 19.19.
bash
En esta demostración, usaremos la sintaxis abreviada para declarar dos tipos anulables, uno doble y uno int. Usamos el valor HasValue en el bloque if para decidir si el valor de la int es correcto o no.
Si tratamos de referirnos a la int sin el bloque if, vemos la siguiente excepción:
1Sistema.OperaciónInválidaExcepción:$0027El objeto anulable debe tener un valor$0027
csharp
Esta excepción aparece en el momento de la compilación. Arreglemos el problema antes de que llegue a la producción.
Convirtamos un tipo anulable en un tipo subyacente.
123456789101112131415161718192021222324252627282930313233 usando el sistema;namespace nllables{classProgram{staticvoidMain(string[] args){doble? d =nulo;int? c =9;int g = c ??99;doble f = d ??99.9; Console.WriteLine("Los nulos...");if(d.HasValue){ Console.WriteLine($"La variable: {nombre de(d)} tiene un valor de {d.Valor}");}else{ Console.WriteLine($"La variable: {nombre(d)} tiene es nula!");}si(c.TieneValor){ Consola.LíneaDeEscritura($"La variable: {nombrede(c)} tiene un valor de {c.Valor}");}else{ Console.WriteLine($"La variable: {nombre(c)} tiene es nula!");} Console.WriteLine("La convertida..."); Console.WriteLine($"La variable: {nombrede(g)} tiene un valor de {g}"); Console.WriteLine($"La variable: {nombre(f)} tiene el valor de {f}"); Console.ReadKey();}}}
csharp
El resultado es el siguiente:
123456Los nulos...La variable: d tiene es nula!La variable: c tiene valor de 9La convertida...La variable: g tiene valor de 9La variable: f tiene valor de 99.9
bash
Tenemos dos variables de tipo nulo, d y c. El operador de coalescencia nula nos permite convertir las variables en lo que respecta a sus valores en variables estándar de tipo g y f.
Nuestra conversión puede necesitar alguna explicación. La int g = c ?? 99; la línea funciona entre bastidores de la siguiente manera. Comprueba si la c es un tipo nulo y llama al operador de HasValue. Si el valor de retorno es verdadero se asigna a g; si no, se asigna 99**. Lo mismo ocurre con el doble f = d ?? 99.9; lo que muestra otro caso, en el que se asigna el valor de la variable so99.9 como el valor de la variable f`. Hay que tener en cuenta que estos valores deben ser implícitamente convertibles en lo que respecta al valor.
Como muestra un simple ejemplo, la siguiente acción morirá con una excepción:
1int g = c ??99.9;
csharp
El error dice:
12CS0266 No se puede convertir implícitamente el tipo $0027doble$0027 a $0027int$0027. Existe una conversión explícita (¿te falta un reparto?)
bash
¿Qué hay de los operadores?
123456789101112131415161718192021222324252627282930313233 usando el sistema;namespace nllables{classProgram{staticvoidMain(string[] args){doble? a =null;double? b =99.9;bool? c =verdadero;bool? d =falso;bool? e =nulo;int? f =10;int? g =nulo; Console.WriteLine("Do the math..."); Console.WriteLine($"a + b = {(a + b)}"); Consola. WriteLine($"a * b = {a * b}"); Console.WriteLine($"a * f = {a * f}"); Console.WriteLine($"b * f = {b * f}"); Console.WriteLine("Las booleanas..."); Console. WriteLine($"c | d = {c | d}"); Console.WriteLine($"c | e = {c | e}"); Console.WriteLine($"d & e = {d & e}"); Console.WriteLine($"c & e = {c | e}"); Console.ReadKey();}}
csharp
El resultado:,
1234c | d = Truec | e = Trued & e = Falsec & e = True
bash
De este experimento, concluimos que cualquier operación en el campo de las matemáticas no produce nada cuando está involucrada con un nulo en cualquiera de los lados. En cuanto a la parte booleana, la situación es un poco más complicada porque la c & e = Verdadero muestra que verdadero & nulo resulta en Verdadero mientras que falso & nulo evalúa a Falso. Este artículo discute más a fondo los operadores lógicos booleanos nulables si te interesa.