null許容参照型とnull許容(値)型
参照型と値型
データの入る型(データ型)には大きく分けて、
クラスと構造体(stract)があり、
クラスに分類されるデータ型を参照型といい、
構造体に分類されるデータ型を値型という。
クラス(参照型)
参照型は、それぞれの固有のデータの他に、nullも代入できる。
C#であればstring型、UnityであればGameObject型、自作したGameManager等のクラス
等がクラスであり、参照型である。
つまり元々、クラス(参照型)自体はnullを代入できるが
それゆえに「Null Reference Exceptonエラー」が発生してしまう。
そのため最近のC#では、
参照型であるクラスも「?」を付けているときだけnullを代入できる機能が追加され、
それが、null許容参照型である。
「string?」のように、参照型であるクラスに「?」を付けることで、null許容参照型となる。
そしてこの機能を利用する場合、単にstringと宣言した場合には、null が代入できない状態になる。
「クラス(参照型)は、元々nullが代入できる型であるが
それに明示的に「?」を付けたときだけnullを代入できるようにし、
それ以外では、クラス(参照型)であってもnullを代入できないようにすることで
nullチェックの処理や、nullエラー自体を無くす」
というのが、null許容参照型の趣旨である。
ただし現在は、これはプレビュー機能であり、
採用しても良いが、エラーまみれになる。
なぜなら「GameObject obj;」と記述してある場合、
本来なら自動的にnullが代入されるが、null許容参照型からみればルール違反となるためである。
「こういう方法もある」とだけ覚えておくといい。
構造体(値型)
一方、構造体は値型というデータ型であり、
構造体(値型)にはnullはないため、
構造体(値型)にnullを代入しようとするとエラーになる。
つまり、「int x = null;」と記述しても代入できないため、エラーになる。
そして、構造体(値型)にはnullの状態が100%ないため、null エラーは出ない。
しかし、状態によっては、enumのように
構造体(値型)であってもnullを代入して欲しいケースがある。
その場合、「?」をつけることで、
本来は固有のデータしか入らない構造体(値型)に対して、nullを代入出来るようになる。
要するに、「int? x = null;」と記述すれば、
本来なら整数しか入らないデータ型である構造体のint型にnullを代入することが出来るのである。
これをnull許容型(null許容値型)という。
以前はnull許容型といえば値型しかなかったが、
C#8.0以降では参照型でもnull許容ができるようになり、
区別するために両方の表現がある。
まとめ
型の宣言時に、その型が「クラス(参照型)なのか、構造体(値型)なのか」で
「?」の持つ役割が「null許容参照型なのかnull許容値型なのか」に区別される。
プログラムの本質として、「データの型が参照型なのか値型なのか」を理解しておかなければ
「?」の部分は正確に把握できないため、
コードを書く際に常に「?」の意味や「参照型・値型」を意識しろ。
コメント