Perché la proprietà Nullable HasValue non genera NullReferenceException su Nulls?

Considera il seguente codice:

DateTime? ndate = null; Console.WriteLine(ndate.HasValue); 

Mi sarei aspettato una NullReferenceException, ma HasValue restituirà effettivamente false. Tuttavia, poiché ndate è nullo, come viene eseguita la chiamata della proprietà, poiché non esiste alcun object per richiamare la proprietà HasValue?

Tecnicamente, “ndate” non è nullo: è un tipo di valore, con il valore specificato come null.

Quando scrivi DateTime? , questo è solo una scorciatoia per Nullable , che è una struttura. Non c’è modo per questo di essere tecnicamente nullo, dal momento che non è un tipo di riferimento.

Il Nullable è una struttura, in pratica non può contenere un valore null .

Il tuo compito, in realtà è compilato in qualcosa che assomiglia a questo:

 Nullable ndate = new Nullable(); 

Un altro esempio, l’espressione:

 int? a = null; 

Genera il seguente IL:

 .locals init (valuetype [mscorlib]System.Nullable`1 V_0) IL_0000: ldloca.s V_0 IL_0002: initobj valuetype [mscorlib]System.Nullable`1 

Una chiamata all’operazione initobj , che inizializza ciascun campo del tipo di valore in un indirizzo specificato su un riferimento null o uno 0 del tipo primitivo appropriato.

In conclusione, ciò che sta accadendo qui è l’ inizializzazione della struct predefinita.

Mi sarei aspettato una NullReferenceException

Non esiste alcun riferimento nullo sottoposto a dereferenziazione, quindi “NullReferenceException” non dovrebbe essere previsto. Il valore DateTime nullable non è un riferimento null . È un valore nullo .

Tuttavia, poiché ndate è nullo, come viene eseguita la chiamata della proprietà, poiché non esiste alcun object per richiamare la proprietà HasValue?

La domanda presuppone una premessa sbagliata. C’è un object. Esiste un valore DateTime nullable che rappresenta il valore null di un DateTime nullable. Quel valore è un object.

Considera il tuo codice:

 DateTime? ndate = null; Console.WriteLine(ndate.HasValue); 

Questo è solo un modo breve di scrivere qualcosa che è logicamente come:

 DateTime ndate = default(DateTime); bool ndateHasValue = false; Console.WriteLine(ndateHasValue); 

Un tipo di valore nullable è semplicemente un modo piacevole per scrivere codice che significa “si prega di albind un booleano a questa cosa che tiene traccia di se è logicamente nullo o meno”.

Quello che succede veramente è che una vera e propria struttura Nullable (non nulla) viene assegnata alla variabile, quindi la variabile non è nulla ma è Value.

Zucchero sintattico amico mio … il compilatore lo trasforma. Chiamata di HaseValue in codice che non genera un’eccezione 🙂