この章のテーマ §
ボックス化、null 許容値型、null 許容参照型について学びます。似ているところはあるものの、これらは全て別物です。
前提知識 §
Console.WriteLineメソッド, 文字列の基礎, 変数の基礎, int型, string型, 継承の基礎. キャスト
解説 §
ボックス化、null 許容値型、null 許容参照型は、似ているところもありますが、全て別の機能です。
ボックス化は、値型の値を参照型の変数などに入れる場合、自動的に発生します。たとえば、int型はobject型を継承元の祖先に持つので、object型の変数に代入できます。しかし、int型は値型で、object型は参照型で、通常は構造が違いすぎて代入ができません。そこで、値型の入れ物となる参照型の箱(ボックス)を用意し、この中に値を入れて見かけ上参照型として扱えるようにします。これがボックス化という処理です。ボックス化した値はキャストで、元の型に戻すとボックス化解除が自動的に行われて、値は箱から取り出されます。
null 許容値型は、null値を取ることができない値型に、null値を扱う能力を追加する機能です。型名の後ろに?記号を追加すると、元の型と同じ表現力を持ち、null値も代入可能で、参照型として扱える型に進化させることができます。たとえば、int型に対応するnull 許容値型はint?となります。
null 許容参照型は、同じように型名に?記号を追加した名前を持ちますが、役割が違います。これは、nullを許容しないコンテキストで、null値を代入可能な型へのnull値の代入を明示的に許容するために使用されます。参照型は最初からnull値を代入可能なので、特別な機能が追加されるわけではありません。コンパイラの制限が解除されるだけです。
罠の数々 §
- ボックス化、null 許容値型、null 許容参照型は似ている部分もあるが、それぞれ別物である。特に、null 許容値型、null 許容参照型はソースコード上ではそっくりに見える。int?とstring?は同じようにみえる。しかし、同じではないので注意しよう
- ボックス化された値型に対応する型名は存在しない。値型をあくまで参照型として使いたいだけなら、null 許容値型を使うのも手である
参考リンク §
null 許容値型 (C# リファレンス)
Null 許容参照型 (C# リファレンス)
ボックス化とボックス化解除 (C# プログラミング ガイド)
サンプルソース: nullable §
Console.WriteLine("ボックス化とボックス化解除");
int a = 123;
// ボックス化
object o = a;
// ボックス化解除
int b = (int)o;
Console.WriteLine($"b={b}");
Console.WriteLine("null 許容値型");
int? c = 123;
c = null;
c = 456;
Console.WriteLine($"c={c}");
Console.WriteLine("null 許容参照型");
string? s = "the Jedi";
s = null;
s = "Return of the Jedi";
Console.WriteLine($"s={s}");
実行結果 §
ボックス化とボックス化解除
b=123
null 許容値型
c=456
null 許容参照型
s=Return of the Jedi
リポジトリ §
https://github.com/autumn009/CSharpPrimer2
練習問題 §
以下のプログラムの実行結果を予測してみよう。ちなみに、Console.WriteLineでnullを出力しようとすると、特に例外は起きず何も出力されない。
int? a = 1;
int? b = null;
int? c = a+b;
Console.WriteLine($"c={c}/c is null:{c==null}");
- c=1/c is null:False
- c=/c is null:False
- c=/c is null:True
- 実行時例外
- コンパイルエラーになる
[[解答]]