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;

というようなチェック付き演算を行うことができます。