Investigué un poco sobre esto mediante el uso de diferentes métodos para asignar valores a un int anulable. Esto es lo que sucedió cuando hice varias cosas. Debería aclarar lo que está pasando. Tenga en cuenta: Nullable<something>
o la taquigrafía something?
es una estructura para la cual el compilador parece estar haciendo mucho trabajo para permitirnos usar con nulo como si fuera una clase.
Como verá a continuación, SomeNullable == null
y SomeNullable.HasValue
siempre devolverá un verdadero o falso esperado. Aunque no se muestra a continuación, también SomeNullable == 3
es válido (suponiendo que SomeNullable es un int?
).
Aunque SomeNullable.Value
no nos lleva a un error de ejecución, si asignamos null
a SomeNullable
. De hecho, este es el único caso en el que los valores nulables pueden causarnos un problema, gracias a una combinación de operadores sobrecargados, sobrecargadosobject.Equals(obj)
método y optimización del compilador y negocios de monos.
Aquí hay una descripción de algún código que ejecuté y qué salida produjo en las etiquetas:
int? val = null;
lbl_Val.Text = val.ToString(); //Produced an empty string.
lbl_ValVal.Text = val.Value.ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValEqNull.Text = (val == null).ToString(); //Produced "True" (without the quotes)
lbl_ValNEqNull.Text = (val != null).ToString(); //Produced "False"
lbl_ValHasVal.Text = val.HasValue.ToString(); //Produced "False"
lbl_NValHasVal.Text = (!(val.HasValue)).ToString(); //Produced "True"
lbl_ValValEqNull.Text = (val.Value == null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValValNEqNull.Text = (val.Value != null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
Ok, intentemos el siguiente método de inicialización:
int? val = new int?();
lbl_Val.Text = val.ToString(); //Produced an empty string.
lbl_ValVal.Text = val.Value.ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValEqNull.Text = (val == null).ToString(); //Produced "True" (without the quotes)
lbl_ValNEqNull.Text = (val != null).ToString(); //Produced "False"
lbl_ValHasVal.Text = val.HasValue.ToString(); //Produced "False"
lbl_NValHasVal.Text = (!(val.HasValue)).ToString(); //Produced "True"
lbl_ValValEqNull.Text = (val.Value == null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValValNEqNull.Text = (val.Value != null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
Todo lo mismo que antes. Tenga en cuenta que la inicialización con int? val = new int?(null);
, con nulo pasado al constructor, habría producido un error de tiempo de COMPILACIÓN, ya que el VALOR del objeto anulable NO es anulable. Es solo el objeto contenedor lo que puede ser igual a nulo.
Del mismo modo, obtendríamos un error de tiempo de compilación de:
int? val = new int?();
val.Value = null;
sin mencionar que val.Value
es una propiedad de solo lectura de todos modos, lo que significa que ni siquiera podemos usar algo como:
val.Value = 3;
pero de nuevo, los operadores de conversión implícita sobrecargados polimorfos nos permiten hacer:
val = 3;
Sin embargo, no es necesario preocuparse por lo polis que puede hacer, siempre y cuando funcione correctamente. :)