Null 許容型の使用 (C# プログラミング ガイド)
更新 : 2007 年 11 月
Null 許容型は、基底の型のすべての値に加えて、null 値を表すことができます。Null 許容型は、次のいずれかの形式で宣言します。
System.Nullable<T> variable
または
T? variable
T は、Null 許容型の基底の型です。T には、struct を含む任意の値型を指定できますが、参照型は指定できません。
Null 許容型を使用するときの例として、通常のブール型変数が、true と false の 2 つの値をどのように持つことができるかを考えてみましょう。この変数には、"未定義" を示す値はありません。多くのプログラミング アプリケーションの中でも特にデータベース操作では、変数が未定義の状態で現れることがあります。たとえば、データベース フィールドには、true や false の値が入力されている場合がありますが、値が入力されていない場合もあります。また、参照型に null を設定すると、その型が初期化されていないことを示すことができます。
このような違いから、ステータス情報を格納する変数を追加したり、特別な値を使用したりするような余分なプログラミング作業が生じることがあります。C# では、Null 許容型修飾子により、未定義の値を示す値型変数を作成できます。
Null 許容型の例
Null 許容型の基底の型には、任意の値型を使用できます。次に例を示します。
int? i = 10;
double? d1 = 3.14;
bool? flag = null;
char? letter = 'a';
int?[] arr = new int?[10];
Null 許容型のメンバ
Null 許容型の各インスタンスには、次のような読み取り専用の 2 つのパブリック プロパティがあります。
HasValue
HasValue は bool 型です。変数が null 以外の値を格納している場合、このプロパティには true が設定されます。
Value
Value は、基底の型と同じ型です。HasValue が true の場合、Value は、有意な値を格納しています。HasValue が false の場合、Value にアクセスすると、InvalidOperationException がスローされます。
次の例では、HasValue メンバを使用して、値を表示する前に、変数に値が格納されているかどうかをテストします。
int? x = 10;
if (x.HasValue)
{
System.Console.WriteLine(x.Value);
}
else
{
System.Console.WriteLine("Undefined");
}
値のテストは、次の例のように行うこともできます。
int? y = 10;
if (y != null)
{
System.Console.WriteLine(y.Value);
}
else
{
System.Console.WriteLine("Undefined");
}
明示的な変換
Null 許容型は、キャストを明示的に使用するか、または Value プロパティを使用して通常の型にキャストできます。次に例を示します。
int? n = null;
//int m1 = n; // Will not compile.
int m2 = (int)n; // Compiles, but will create an exception if x is null.
int m3 = n.Value; // Compiles, but will create an exception if x is null.
2 つのデータ型の間でユーザー定義変換を定義している場合は、これらのデータ型の Null 許容バージョンを使用して、同じユーザー定義変換を実行することもできます。
暗黙の型変換
Null 許容型の変数には、次の例のように null キーワードを使用して null に設定できます。
int? n1 = null;
通常の型から Null 許容型への変換は暗黙的です。
int? n2;
n2 = 10; // Implicit conversion.
演算子
定義済みの単項演算子と二項演算子およびユーザー定義演算子は、いずれも値型を対象にしていますが、Null 許容型でも使用できます。これらの演算子は、オペランドが null の場合は null 値を生成し、null 以外の場合は、包含されている値に基づいて結果を算出します。次に例を示します。
int? a = 10;
int? b = null;
a++; // Increment by 1, now a is 11.
a = a * 10; // Multiply by 10, now a is 110.
a = a + b; // Add b, now a is null.
2 つの Null 許容型を比較したときに、Null 許容型のいずれかが null の場合は、常に false と評価されます。そのため、比較した結果が false であっても、逆のケースが true とは限りません。次に例を示します。
int? num1 = 10;
int? num2 = null;
if (num1 >= num2)
{
System.Console.WriteLine("num1 is greater than or equal to num1");
}
else
{
// num1 is NOT less than num2
}
else ステートメントの結果は、num2 が null であり、値を含んでいないため、無効です。
どちらも null である 2 つの Null 許容型を比較すると、結果は true になります。
?? 演算子
?? 演算子は、Null 許容型が Null 許容型以外の型に割り当てられているときに返す既定値を定義します。
int? c = null;
// d = c, unless c is null, in which case d = -1.
int d = c ?? -1;
この演算子は、複数の Null 許容型で使用することもできます。次に例を示します。
int? e = null;
int? f = null;
// g = e or f, unless e and f are both null, in which case g = -1.
int g = e ?? f ?? -1;
bool? 型
Null 許容 bool? 型は、true、false、null の 3 つの異なる値を格納できます。bool? から bool にキャストする方法については、「方法 : bool? から bool に安全にキャストする (C# プログラミング ガイド)」を参照してください。
Null 許容ブール型は、SQL で使用するブール変数型と同じです。& 演算子と | 演算子によって生成される結果が SQL の 3 値のブール型と一致するようにするには、次の定義済みの演算子を指定します。
bool? operator &(bool? x, bool? y)
bool? operator |(bool? x, bool? y)
これらの演算子の結果を以下の表に示します。
x |
y |
x&y |
x|y |
---|---|---|---|
true |
true |
true |
true |
true |
false |
false |
true |
true |
null |
null |
true |
false |
true |
false |
true |
false |
false |
false |
false |
false |
null |
false |
null |
null |
true |
null |
true |
null |
false |
false |
null |
null |
null |
null |
null |