2011-04-09 21 views
13

Tengo curiosidad por saber cómo funciona el tipo Nullable detrás de escena. ¿Está creando un nuevo objeto (los objetos pueden asignarse nulo) con un valor posible de nulo?¿Cómo funciona un tipo de Nullable <T> que funciona detrás de escena?

En el ejemplo utilizamos un Nullable <int>, ¿es su tipo de conversión implícita de un objeto a un int y viceversa cuando le asigna un valor nulo?

También sé cómo se puede crear manualmente, ¿hay algún beneficio de utilizar el tipo Nullable en lugar de crearlo nosotros mismos?

+0

@Rfvgyhn No veo realmente cómo esto es un duplicado. Querían saber la diferencia entre un int y un nullable . Esto no es lo que pedí. – loyalpenguin

+0

¡Es un duplicado de 110229! –

+0

@Frank ¿Qué tal si en lugar de tratar de cerrar mi pregunta, publica una respuesta que nos ayude a mí y a la comunidad? Obviamente, hay respuestas aquí que no se han mencionado ni explicado en la pregunta a la que hace referencia. También por segunda vez, no preguntan qué pedí. – loyalpenguin

Respuesta

11

El tipo que admite nulos es una estructura que consta de dos campos: un bool y un T. Cuando el valor es nulo, el bool es falso y el T tiene el valor predeterminado. Cuando el valor no es nulo, el bool es verdadero.

Hay dos ventajas principales de usar Nullable en comparación con la implementación de la funcionalidad usted mismo. Está el soporte de lenguaje, como se describe con más detalle en la respuesta de ChaosPandion, y está el hecho de que el boxeo (convirtiendo a object) eliminará automáticamente el "contenedor" nulo, dejando una referencia nula o el objeto simple T.z

+0

+1 para la gran explicación. ¿Tiene una referencia para esto donde puedo verlo con más detalle? – loyalpenguin

+3

¿En qué aspecto específicamente? http://msdn.microsoft.com/en-us/library/ms228597.aspx explica lo del boxeo. – Random832

+0

Sí, ahí lo tienes. Gracias. – loyalpenguin

1

Nullable<T> se implementa como una estructura que reemplaza Equals() para comportarse como null si HasValue es false. Hay una conversión implícita de T a T?, y una conversión explícita en la otra dirección que arroja si !HasValue.

8

En realidad es bastante simple. El compilador te da una mano con la sintaxis.

// this 
int? x = null; 
// Transformed to this 
int? x = new Nullable<int>() 

// this 
if (x == null) return; 
// Transformed to this 
if (!x.HasValue) return; 

// this 
if (x == 2) return; 
// Transformed to this 
if (x.GetValueOrDefault() == 2 && x.HasValue) return; 
+0

¿Podría verificar (en reflector) que esto es cierto? Esa última línea, al menos, no debería ser necesaria, debido al 'operador implícito Nullable ' (ver [@ respuesta de barrylloyd] (http://stackoverflow.com/questions/5602773/how-does-a-nullablet -type-work-behind-the-scenes/5602820 # 5602820)) –

+0

Ejecuté esto en linqpad y confirmé que la última línea contiene llamadas a las dos propiedades. Tiene que ver con la forma en que se implementa el ==, incluso con otro anulable. 'if (x == y)' se convierte en 'if (x.GetValueOrDefault() == y.GetValueOrDefault() && x.HasValue == y.HasValue)'. – Random832

+0

@BlueRaja - Danny Pflughoeft - Eso es lo que sucede. – ChaosPandion

10

Aquí es el (arreglado) código se ejecute .Net reflector contra anulable ...

[Serializable, StructLayout(LayoutKind.Sequential), TypeDependency("System.Collections.Generic.NullableComparer`1"), TypeDependency("System.Collections.Generic.NullableEqualityComparer`1")] 
public struct Nullable<T> 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>(T value) 
{ 
    return new Nullable<T>(value); 
} 

public static explicit operator T(Nullable<T> value) 
{ 
    return value.Value; 
} 
} 
+0

¿Es esto? ¿Dónde se establece 'hasValue'? –

+2

hasValue está predeterminado en False y solo está establecido en True en el constructor – barrylloyd

+0

Ah, ya veo, es inmutable. No estoy seguro de lo que estaba pensando ...¡Gracias! –

Cuestiones relacionadas