Come funziona un tipo Nullable dietro le quinte?

Sono curioso di sapere come funziona il tipo Nullable dietro le quinte. Sta creando un nuovo object (gli oggetti possono essere assegnati null) con un ansible valore di null?

Nell’esempio usiamo un Nullable , è un qualche tipo di conversione implicita da un object ad un int e viceversa quando gli assegni un valore nullo?

So anche come si può creare questo manualmente, c’è un vantaggio nell’usare il tipo Nullable invece di crearlo noi stessi?

Il tipo nullable è una struttura composta da due campi: un bool e una T Quando il valore è nullo, il valore bool è falso e T ha il valore predefinito. Quando il valore non è nullo, il valore bool è true.

Ci sono due principali vantaggi nell’usare Nullable rispetto all’implementazione della funzionalità da soli. C’è il supporto linguistico, come descritto più dettagliatamente nella risposta di ChaosPandion, e c’è il fatto che il pugilato (la conversione in un object ) rimuoverà automaticamente il “wrapper” nullable, lasciando un riferimento nullo o il semplice object T.z

Ecco il codice (riordinato) da eseguire .Net Reflector contro Nullable …

 [Serializable, StructLayout(LayoutKind.Sequential), TypeDependency("System.Collections.Generic.NullableComparer`1"), TypeDependency("System.Collections.Generic.NullableEqualityComparer`1")] public struct Nullable where T: struct { private bool hasValue; internal T value; public Nullable(T value) { this.value = value; this.hasValue = true; } public bool HasValue { get { return this.hasValue; } } public T Value { get { if (!this.HasValue) { ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue); } return this.value; } } public T GetValueOrDefault() { return this.value; } public T GetValueOrDefault(T defaultValue) { if (!this.HasValue) { return defaultValue; } return this.value; } public override bool Equals(object other) { if (!this.HasValue) { return (other == null); } if (other == null) { return false; } return this.value.Equals(other); } public override int GetHashCode() { if (!this.HasValue) { return 0; } return this.value.GetHashCode(); } public override string ToString() { if (!this.HasValue) { return ""; } return this.value.ToString(); } public static implicit operator Nullable(T value) { return new Nullable(value); } public static explicit operator T(Nullable value) { return value.Value; } } 

In realtà è abbastanza semplice. Il compilatore ti dà una mano con la syntax.

 // this int? x = null; // Transformsd to this int? x = new Nullable() // this if (x == null) return; // Transformsd to this if (!x.HasValue) return; // this if (x == 2) return; // Transformsd to this if (x.GetValueOrDefault() == 2 && x.HasValue) return; 

Nullable è implementato come una struct che HasValue override di Equals() per comportarsi come null se HasValue è false . Esiste una conversione implicita da T a T? e una conversione esplicita nell’altra direzione che getta se !HasValue .