2011-05-20 2 views
25

Voici un code qui démontre que je ne peux pas déclarer et initialiser un type struct comme nul. Le type Nullable est une structure, alors pourquoi suis-je capable de le mettre à null?Les structs ne peuvent-ils vraiment pas être NULL 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"); 
} 

Foo est défini comme

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 question a été répondue (voir ci-dessous). Pour clarifier, je vais poster un exemple. Le code C#:

using System; 

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

produit l'IL suivante:

.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 et b sont déclarés, mais seulement b est initialisé.

+1

Foo? f = null; // Compile –

+1

@Fogotten Point-virgule, pas le point de la question. –

+0

Si vous êtes toujours curieux, essayez d'exécuter 'b.GetType()' après avoir réussi à montrer que 'b.HasValue' est faux. Cela illustre une façon dont un type nullable n'est pas la même chose qu'une structure, puisque vous pouvez déréférencer la nullable 'null' pour accéder à HasValue ou même la méthode Equals, mais toute opération qui encadre le nullable retournera une vraie valeur nulle. –

Répondre

18

Le compilateur C# vous vous fournit un peu de sucre alors faites vraiment ceci:

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

Vous avez raison. Le voir dans ILDASM répond à cela. Avez-vous des références de la part des États membres à ce sujet? C'est une nouvelle pour moi ... – Nate

+0

@Nate, La spécification de langage C# a quelques détails sur la façon dont les types Nullable sont gérés. Il est intéressant de noter que les types Nullable Value ne sont pas des structures; structures et Nullables sont les deux types de valeur, mais le compilateur et CLR donnent un traitement différent à chacun. http://go.microsoft.com/fwlink/?LinkId=199552 –

+0

@Dan, la raison de la question était que j'utilisais un bool?et je me demandais si j'avais besoin de vérifier si l'enveloppe Nullable était in null avant de référencer Nullable .HasValue. J'ai été surpris de découvrir que je ne l'ai pas fait. J'avais pensé que Nullable était un type de classe, mais j'ai découvert qu'il s'agissait d'une structure lors de la lecture de sa définition. Cela m'a amené à me demander pourquoi je pouvais définir un Nullable à null mais pas un struct "régulier". – Nate

12

C# a une certaine syntaxe de sucre qui vous permet d'apparaître pour définir un type Nullable à null. Ce que vous faites en fait sous les couvertures définit la propriété HasValue du type NULL à false.

3

Parce que vous configurez pas réellement la variable Nullable<T> à null. La structure est toujours là. Il représente null via un indicateur de bit interne dans la structure.

Il y a aussi du sucre de compilateur pour faire de la magie dans les coulisses.

2

Vous ne pouvez pas définir une structure sur null, mais vous pouvez avoir des conversions de type implicites, ce qui se passe sous le capot.

+4

Ceci est en réalité plus qu'une simple conversion de type implicite. Le CLR fournit un support spécial pour les types Nullable qui les rendent un peu différents des autres types de valeurs. La plus grande différence est qu'une nullité 'null' est encadrée à une vraie référence nulle et unboxing null va créer un nouveau Nullable qui équivaut à null. –

Questions connexes