web-dev-qa-db-ja.com

構造体はC#で本当にnullにならないのですか?

以下は、構造体型をnullとして宣言および初期化できないことを示すコードです。 Nullable 型は構造体ですが、なぜnullに設定できるのですか?

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は次のように定義されます。

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; }
    }
}

質問に回答しました(以下を参照)。明確にするために、例を投稿します。 C#コード:

using System;

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

次の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とbが宣言されていますが、初期化されるのはbだけです。

29
Nate

C#コンパイラは少し砂糖を提供するので、実際にこれを行っています。

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

これが糖衣構文です

bool? b = null;    
if (b ?? false) 
{
   b = true;
}
24
ChaosPandion

C#には、null許容型をnullに設定しているように見える構文糖衣構文があります。あなたがしていること実際には内部で行っているのは、null許容型のHasValueプロパティをfalseに設定することです。

13
Andrew Hare

実際にはNullable<T>変数をnullに設定していないためです。構造体はまだそこにあります。構造体の内部ビットフラグを介してnullを表します。

舞台裏で魔法を起こさせるためのコンパイラシュガーもあります。

3
Nicholas Carey

構造体をnullに設定することはできませんが、暗黙の型変換を行うことはできます。これは、内部で行われていることです。

2
jmoreno