PR
(鳥山 隆一=TRO)

著者紹介
 IT関連ライター。プログラミングから,IP電話,企業におけるシステム導入まで,IT関連で幅広く活躍。2003年に企業のシステム導入事例の作成を業務の中心とする有限会社TROを設立。IT関連企業の導入事例を多く手がけている。

 今回はC#2.0の新機能の目玉の一つともいえるNullable型について説明しよう。これは整数型や小数点型などの値型の変数でも,文字列型などの参照型の変数と同じようにNull値を取れるようにしたデータ型である。

 Nullableが取り入れられたいきさつは,C#のさらに次のバージョンであるC#3.0で,SQLなどデータベース言語との親和性を高めるためだ。その目的は,将来のOSが備えるファイル・システムによって作られる「ネットワーク・データベース」と,現在主流となっているリレーショナル・データベースとをシームレスに利用できるようにすることである(詳しくはチャンネル9のAnders Hejlsberg氏のインタビューを参照)。

 ところで,Nullableの説明に入る前にお詫びさせてほしい。前回の記事の訂正である。エディット・コンティニュ(E&C)がVBで復活したと書いたので,E&Cが利用できるのはVBだけと考えてしまった読者も多かったかもしれない。しかし実際はC#でも利用できるようになる。VS2005の初期の発表時,この機能はC#に盛り込まない予定だったが,ベータ・ユーザーなどからの要望が強かったため,急きょ盛り込むことが決定して,ベータ2から実装された。

 ほかにもベータ2とベータ1では仕様が変えられている部分がある。さらには製品版でベータ2から変更が予定されている機能がある。この記事はベータ2を基に書いているので,ベータ1で実行した場合に結果が異なることがあるかもしれない。また,できるだけ製品版で修正される予定の機能については避けるようにした。

Nullable型の定義と利用
 ここではNullable型を,32ビット符号付き整数型(int型)を例に挙げて説明するが,ほかのビット数の整数型や浮動小数点型(float型やdouble型)などでも同様である。

 まず,変数をNullに初期化することを考えよう。MyStringという文字列型変数と,MyIntという整数型変数を定義してNullに設定するコードは以下のように考えられるだろう。

string MyString = null;
int MyInt = null;

 しかし,残念なことにこのコードはコンパイルできない。整数型(int型)にはNullを代入できないのだ。Nullを代入するためには,Nullable整数型の変数を使う必要がある。Nullable型変数を宣言するには,以下のように“?”シンタックスを使う。

string MyString = null;
int? MyInt = null;

 さて,整数や小数点などを扱う変数にNullを設定できるようになると,いくつかの疑問が生じるだろう。まずはNullable型変数と非Nullable型変数との間の値の代入だ。

 Nullable型変数に非Nullable型変数の値を代入するときには,暗黙の型変換が行われる。int型とint?型,long型とlong?型,double型とdouble?型のように,精度が同じならばどのような値でも代入でき,例外は発生しない。

 一方,非Nullable型変数に,Nullable型変数の値を代入するときは,キャストが必要である。そして,Nullable型変数の値がNullのときに例外が発生する。

int? MyNullableInt;
int MyInt;

MyNullableInt = 16;
MyInt = (int)MyNullableInt;// 問題なく代入できる

MyNullableInt = null;
MyInt = (int)MyNullableInt;// 例外が発生して実行できない

 この例では,同じ変数同士の代入でも,例外が発生しないときと,発生するときがあることを示した。Nullable型変数に整数値を格納し,それを非Nullable型変数に代入したときは例外は発生しない。しかし,Nullable型変数にNullを代入し,それを非Nullable型変数に代入しようとすると例外が発生する。

 次は演算子を見てみる。まずはコードを見て結果を想像してほしい。

int? MyNullableIntA, MyNullableIntB, MyNullableIntC;

MyNullableIntA = 3;
MyNullableIntB = 2;
MyNullableIntC = MyNullableIntA + MyNullableIntB;//(1)

MyNullableIntA = null;
MyNullableIntC = MyNullableIntA + MyNullableIntB;//(2)

MyNullableIntC = (int)MyNullableIntA + MyNullableIntB;//(3)

 最初の(1)の加算では,MyNullableIntCには,MyNullableIntAとMyNullableIntBの値の和,つまり5が代入される。次の(2)の,Nullと数値の加算は,例外にはならず,MyNullableIntCにはNullが代入される。このように,通常の演算子の機能をNullのときに拡張させたものをLifted Operatorsと呼ぶ。最後の(3)は,NullであるMyNullableIntAの値をint型にキャストしようとした時点で例外になる。

 ここでは加算について示したが,減算,乗算,除算のいずれも,Nullとの演算結果はすべてNullになる。少し違和感を感じるかもしれないのは,数値をNullで割った場合かもしれない。

int? MyNullableIntA, MyNullableIntB, MyNullableIntC;

MyNullableIntA = null;
MyNullableIntB = 2;
MyNullableIntC = MyNullableIntB / MyNullableIntA;

MyNullableIntA = 0;
MyNullableIntC = MyNullableIntB / MyNullableIntA; //例外が発生する

 例では,数値をNullで割った場合と,0で割った場合を示したが,Nullで割った場合は,例外は発生せずに,MyNullableIntCにはNullが代入される。しかし0で割ろうとすると,当然だが,例外が発生する。

 Nullable型について,概要は分かっていただけただろう。次回はNullable型の変数を使った比較や,C#2.0で追加されたNullを値に置き換えるためのNull coalescing演算子について紹介する。