Nullable`1
値型に対して null を代入可能とするコンテナクラス。
HasValue と Value という2つのプロパティを主に利用する他、== および != による null との比較をサポートします。
C# では Int32 を int、Int64 を long と書けるように、Nullable<T> を T? と記述することができます。
int? x = xxx.GetValue(); Nullable= xxx.GetValue();
また、C# では Nullable のための演算子 ?? があります。
object o = left ?? right; object o = left.HasValue ? left : right; object o = Nullable.GetValueOrDefault(left, right);
の3行はまったく同じ結果になるという非常に単純な演算子ですが、短い記述は好きなので個人的には好んで使うようになりそうです。
Generics の時に記載するつもりでしたが、3行目の書き方に違和感がある方もおられるかもしれません。つまり、
int? x = xxx; int y = Nullable.GetValueOrDefault(x, 0); int z = Nullable.GetValueOrDefault(x, 0);
この2行目と3行目の違いですが、まったくありません。
Nullable.GetValueOrDefault を呼び出している時点では、まだ Nullable に必要な型パラメータ T を渡していませんが、最初の引数に Nullable<int> である int? 型の変数 x を指定した時点で、式全体として Nullable`1!0 が int であると確定します。
このため、Nullable.GetValueOrDefault() という関数呼び出しは自動的に Nullable<int>.GetValueOrDefault() に解決されます。
よって、
int? x = xxx; int y = x ?? 0;
というコードは、x が null の場合に 0 が帰り、x が !null であれば (int)x が返るので、y の型は int であることが保障されるため、コンパイルエラーとはなりません。
しかし
int? v = expr ? 5 : null;
これは、null を (int?)null としないとコンパイルエラーになります。
他にも、
int? x = xxx; int? y = x + 1; int? z = x + y;
のような式を書くことができ、
int? y = x.HasValue ? (int)x + 1 : (int?)null; int? z = (x.HasValue && y.HasValue) ? (int)x + (int)y : (int?)null;
というようなチェック付き演算を行うことができます。