2011-05-20 13 views
25

A continuación se muestra un código que demuestra que no puedo declarar e inicializar un tipo de estructura como nulo. El tipo Nullable es una estructura, entonces ¿por qué puedo configurarlo como nulo?¿Pueden las estructuras realmente no ser nulas en C#?

Nullable<bool> b = null; 
if (b.HasValue) 
{ 
    Console.WriteLine("HasValue == true"); 
} 

//Does not compile... 
Foo f = null; 
if (f.HasValue) 
{ 
    Console.WriteLine("HasValue == true"); 
} 

Dónde Foo se define como

public struct Foo 
{ 
    private bool _hasValue; 
    private string _value; 

    public Foo(string value) 
    { 
     _hasValue = true; 
     _value = value; 
    } 

    public bool HasValue 
    { 
     get { return _hasValue; } 
    } 

    public string Value 
    { 
     get { return _value; } 
    } 
} 

La pregunta ha sido contestada (véase más adelante). Para aclarar, publicaré un ejemplo. El código C#:

using System; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Nullable<bool> a; 
     Nullable<bool> b = null; 
    } 
} 

produce el siguiente IL:

.method private hidebysig static void Main(string[] args) cil managed 
{ 
    .entrypoint 
    // Code size  10 (0xa) 
    .maxstack 1 
    .locals init ([0] valuetype [mscorlib]System.Nullable`1<bool> a, 
      [1] valuetype [mscorlib]System.Nullable`1<bool> b) 
    IL_0000: nop 
    IL_0001: ldloca.s b 
    IL_0003: initobj valuetype [mscorlib]System.Nullable`1<bool> 
    IL_0009: ret 
} // end of method Program::Main 

a y b son declarados, pero sólo b se inicializa.

+1

Foo? f = nulo; // Compila –

+1

@Forgotten Semicolon, no es el punto de la pregunta. –

+0

Si todavía tiene curiosidad, intente ejecutar 'b.GetType()' después de haber demostrado correctamente que 'b.HasValue' es falso. Esto demuestra una forma en que un tipo que admite nulos no es lo mismo que una estructura, ya que puedes desreferenciar el valor nulo 'nulo' para acceder a HasValue o incluso al método Equals, pero cualquier operación que encasilla el valor nulo arrojará un verdadero nulo. –

Respuesta

18

El compilador de C# le proporciona un poco de azúcar por lo que realmente está haciendo esto:

Nullable<bool> b = new Nullable<bool>(); 
+0

Tiene razón. Al verlo en ILDASM, lo responde. ¿Tiene alguna referencia de MS sobre el asunto? Esto es nuevo para mí ... – Nate

+0

@Nate, la especificación del lenguaje C# tiene algunos detalles sobre cómo se manejan los tipos anulables. Vale la pena señalar que los tipos de Valor Nullable no son estructuras; las estructuras y Nullables son ambos tipos de valor, pero el compilador y CLR dan un tratamiento diferente a cada uno. http://go.microsoft.com/fwlink/?LinkId=199552 –

+0

@Dan, el motivo de la pregunta era: ¿estaba usando un bool?y me pregunté a mí mismo si tenía que comprobar si el contenedor Nullable que estaba era nulo antes de hacer referencia a Nullable .HasValue. Me sorprendió descubrir que no lo hice. Pensé que Nullable era un tipo de clase, pero descubrí que era una estructura al leer su definición. Eso me hizo preguntarme por qué podría establecer un Nullable para null pero no como una estructura "regular". – Nate

12

C# tiene un nivel de azúcar de sintaxis que le permite aparentar establecer un tipo que admite nulos en null. Lo que usted es en realidad haciendo bajo las sábanas está estableciendo la propiedad HasValue del tipo nulable en false.

3

Debido a que usted no está realmente estableciendo la variable de Nullable<T> a null. La estructura todavía está allí. Representa null a través de un indicador de bit interno en la estructura.

También hay algo de azúcar en el compilador para que la magia suceda detrás de escena.

2

No puede establecer una estructura como nula, pero puede tener conversiones de tipo implícitas, que es lo que está sucediendo debajo del capó.

+4

Esto es más que una conversión de tipo implícita. El CLR proporciona soporte especial para los tipos anulables que los hacen un poco diferentes de otros tipos de valores. La mayor diferencia es que un Nullable 'nulo' está encuadrado en una referencia nula verdadera y nulo unboxing creará un nuevo Nullable que equivale a nulo. –

Cuestiones relacionadas