Te recomendamos que pruebes esta solución en un entorno controlado antes de enviarlo a producción, saludos.
Solución:
El key para entender lo que null!
significa entender el !
operador. Es posible que lo haya usado antes como el operador “no”. Sin embargo, desde C # 8.0 y su nueva función “tipos de referencia que aceptan valores NULL”, el operador obtuvo un segundo significado. Se puede utilizar en un escribe para controlar la capacidad de nulos, se denomina “Operador de perdón de nulos”
Uso típico
Asumiendo esta definición:
class Person
// Not every person has a middle name. We express "no middle name" as "null"
public string? MiddleName;
El uso sería:
void LogPerson(Person person)
Console.WriteLine(person.MiddleName.Length); // WARNING: may be null
Console.WriteLine(person.MiddleName!.Length); // No warning
Este operador básicamente apaga el compilador null comprueba este uso.
Explicación técnica
Seguridad nula
C # 8.0 intenta ayudarlo a administrar su null
-valores. En lugar de permitirle asignar null
a todo de forma predeterminada, han cambiado las cosas y ahora requieren que explícitamente marque todo lo que desee para poder realizar un null
valor.
Esta es una característica muy útil, le permite evitar NullReferenceException
s obligándote a tomar una decisión y haciéndola cumplir.
Cómo funciona
Hay 2 estados en los que puede estar una variable, cuando se habla de null-seguridad.
- Nullable – Poder ser null.
- No anulable – No puede ser null.
Desde C # 8.0, todos los tipos de referencia no aceptan valores NULL de forma predeterminada. ¡Los tipos de valor no admiten nulos desde C # 2.0!
La “capacidad de nulos” se puede modificar mediante 2 operadores nuevos (nivel de tipo):
!
= deNullable
aNon-Nullable
?
= deNon-Nullable
aNullable
Estos operadores son contrapartes entre sí. El compilador utiliza la información que usted define con esos operadores para garantizar null-seguridad.
Ejemplos de
?
Uso del operador.
Este operador le dice al compilador que una variable puede contener un null valor.
-
Anulable
string? x;
x
es un tipo de referencia, por lo que, de forma predeterminada, no acepta valores NULL.- Aplicamos el
?
operador, lo que lo hace anulable. x = null
Funciona bien.
-
No anulable
string y;
y
es un tipo de referencia, por lo que, de forma predeterminada, no acepta valores NULL.y = null
Genera una advertencia ya que asigna un null valor a algo que no se supone que sea null.
Es bueno saber: Usando string?
es azúcar sintáctico para System.Nullable
!
Uso del operador.
Este operador le dice al compilador que algo que podría ser null, es seguro acceder a él. Expresas la intención de “no preocuparte” por null seguridad en este caso.
string x;
string? y;
x = y
- ¡Ilegal!
Warning: "y" may be null
- El lado izquierdo de la asignación no admite nulos, pero el lado derecho sí.
- Entonces lo hace no funciona, ya que es semánticamente incorrecto
- ¡Ilegal!
x = y!
- ¡Legal!
y
es un tipo de referencia con el?
Se aplicó el modificador de tipo, por lo que es anulable si no se prueba lo contrario.- Aplicamos
!
ay
cual anula su configuración de nulabilidad para que sea no anulable - El lado derecho e izquierdo de la asignación no admite nulos. Lo cual es semánticamente correcto.
ADVERTENCIA El
!
El operador solo desactiva las comprobaciones del compilador a nivel de sistema de tipos: en tiempo de ejecución, el valor aún puede ser null.
¡Úselo con cuidado!
Deberías intentar evitar utilizando el operador nulo-perdonador, el uso puede ser el síntoma de una falla de diseño en su sistema, ya que niega los efectos de null-Seguridad garantizada por el compilador.
Razonamiento
Utilizando el !
El operador creará errores muy difíciles de encontrar. Si tiene una propiedad marcada como no anulable, asumirá que puede usarla de manera segura. Pero en tiempo de ejecución, de repente te encuentras con un NullReferenceException
y rascarte la cabeza. Dado que un valor se convirtió en realidad null después de pasar por alto las comprobaciones del compilador con !
.
Entonces, ¿por qué existe este operador?
Hay casos de uso válidos (descritos en detalle a continuación) donde el uso es apropiado. Sin embargo, en el 99% de los casos, estará mejor con una solución alternativa. Por favor, no abofetee a docenas de !
está en su código, solo para silenciar las advertencias.
- En algunos casos (extremos), el compilador no es capaz de detectar que un valor anulable es en realidad no anulable.
- Migración de base de código heredada más fácil.
- En algunos casos, simplemente no te importa si algo se vuelve null.
- Cuando trabaje con pruebas unitarias, es posible que desee comprobar el comportamiento del código cuando
null
viene a través de.
¿¡OK!? Pero que hace null!
¿significar?
Le dice al compilador que null
no es un nullable
valor. Suena raro, ¿no?
Es lo mismo que y!
del ejemplo anterior. Solo se ve extraño ya que aplica el operador al null
literal. Pero el concepto es el mismo. En este caso, el null
literal es lo mismo que cualquier otra expresión / tipo / valor / variable.
El null
¡El tipo literal es el único tipo que acepta valores NULL de forma predeterminada! Pero como aprendimos, la nulabilidad de ningún el tipo se puede anular con !
a no anulable.
El sistema de tipos no se preocupa por el valor real / en tiempo de ejecución de una variable. Solo su tipo de tiempo de compilación y en su ejemplo la variable que desea asignar a LastName
(null!
) es non-nullable
, que es válido en lo que respecta al sistema de tipos.
Considere este fragmento de código (inválido).
object? null;
LastName = null!;
Cuando la función “tipos de referencia que aceptan valores NULL” está activada, el compilador rastrea qué valores en su código cree que pueden ser null O no. Hay ocasiones en las que el compilador puede tener conocimientos insuficientes.
Por ejemplo, puede estar usando un patrón de inicialización retrasada, donde el constructor no inicializa todos los campos con real (nonull) valores, pero siempre llama a un método de inicialización que garantiza que los campos no sonnull. En tal caso, se enfrenta a una compensación:
- si marca el campo como anulable, el compilador está contento, pero tiene que verificar no necesariamente null cuando usas el campo,
- si deja el campo como no anulable, el compilador se quejará de que los constructores no lo inicializan (puede suprimirlo con
null!
), el campo se puede utilizar sin null cheque.
Tenga en cuenta que al utilizar el !
operador de supresión, está asumiendo algún riesgo. Imagínese que en realidad no está inicializando todos los campos con la coherencia que pensaba. Entonces el uso de null!
inicializar un campo oculta el hecho de que un null
está entrando. Algún código desprevenido puede recibir un null
y por lo tanto fracasar.
De manera más general, es posible que tenga algún conocimiento del dominio: “si verifiqué un método determinado, entonces sé que algún valor no null”:
if (CheckEverythingIsReady())
// you know that `field` is non-null, but the compiler doesn't. The suppression can help
UseNonNullValueFromField(this.field!);
Nuevamente, debe estar seguro de la invariante de su código para hacer esto (“Lo sé mejor”).
Si sostienes algún incógnita y forma de modernizar nuestro crónica te insinuamos escribir una glosa y con deseo lo leeremos.