para - C#Operador de navegación segura: ¿qué está pasando realmente?
operador/= en c++ (3)
He estado siguiendo la característica de operador de navegación segura agregada en C # 6 con cierto interés. Lo he estado esperando por un tiempo. Pero estoy encontrando un comportamiento diferente del que esperaba. Me estoy dando cuenta de que realmente no entiendo cómo funciona realmente.
Dada esta clase
class Foo {
public int? Measure;
}
Aquí hay un código usando el nuevo operador.
Foo f = new Foo { Measure = 3 };
Console.WriteLine(f?.Measure); // 3
f = new Foo { Measure = null };
Console.WriteLine(f?.Measure); // null
f = null;
Console.WriteLine(f?.Measure); // null
Hasta aquí, todo está funcionando como se esperaba. ?.
está accediendo a los miembros cuando el lado izquierdo no está nulo, de lo contrario, se vuelve nulo. Pero aquí las cosas van en una dirección que no esperaba.
var i = f?.Measure; // i is Nullable<int>
Console.WriteLine(i.HasValue); // false
Console.WriteLine(f?.Measure.HasValue); // null
¿Qué?
¿Por qué puedo obtener HasValue
de i
, pero no de la misma expresión que HasValue
a i
? ¿Cómo puede HasValue
ser nulo?
Edición: mi pregunta real es sobre el comportamiento del programa, no un error de compilación. Eliminé el contenido adicional sobre la compilación, y enfocé esta pregunta más estrechamente en por qué dos resultados diferentes son devueltos por lo que parece ser la misma lógica.
Vamos a caminar a través de esto lógicamente.
var f = ???;
var i = f?.Measure;
var t = i.HasValue;
No sabemos si f
es nulo o no.
- Si
f
es nulo, entonces el resultado (i
) esnull
- Si
f
no es nulo, entonces el resultado (i
) es unint
Por lo tanto, i
se define como int?
y t
es un bool
Ahora, vamos a caminar a través de esto:
var f = ???;
var i = f?.Measure.HasValue;
- Si
f
es nulo, entonces el resultado (i
) es nulo - Si
f
no es nulo, entonces el resultado (i
) esMeasure.HasValue
, que es un bool.
Por lo tanto, i
es un bool?
.
Si f
es nulo, cortocircuitamos y devolvemos nulo. Si no es así, devolvemos el resultado bool
de .HasValue
.
Esencialmente, cuando se usa ?.
- el tipo de retorno debe ser un valor de referencia, o un Nullable<T>
, ya que la expresión puede Nullable<T>
un cortocircuito para devolver un valor nulo.
Nullable<T>
es en realidad una estructura y, por lo tanto, no puede ser nulo, solo su Value
puede, por lo que HasValue
siempre estará accesible.
var i = f?.Measure; // i is Nullable<int>
Console.WriteLine(i.HasValue); // false
Console.WriteLine(f?.Measure.HasValue); // null
En este caso, f es nulo.
La razón por la que i.HasValue
devolvió false
es porque i
es de tipo Nullable<int>
. Entonces, incluso cuando el valor de i
es nulo, como en este caso, i.HasValue
sigue siendo accesible.
Sin embargo, f?.Measure.HasValue
devuelve inmediatamente null
después de f?
es evaluado De ahí el resultado que ves arriba.
Solo para citar el comentario de Rob :
Lo principal a tener en cuenta es que estás leyendo y comprendiendo esto: f? .Meaure.HasValue como esto: (f? .Measure) .HasValue, que no es.