i-school - データ型による null 許容型の扱いについて

データ型


 null 許容型の説明の前に、まず、データとしてのデータ型のことを知る必要があります。
データの入る型には大きく分けて、参照型(クラスなど)と値型(構造体(stract)など)があります。


参考サイト
MicroSoft
値型
MicroSoft
参照型


参照型


 変数に対して情報をコピーではなく参照で管理するものは参照型といいます。
それぞれの固有のデータの他に、null という情報が代入出来ます。
C# であれば、string 型、Unity であれば GameObject 型、自作した GameManager などのクラスなどがクラスです。

 つまり元々、クラス自体は null を代入できるのですが、それゆえに Null Reference Excepton エラーが発生します。


値型


 変数に対して情報をコピーして代入し、元のデータとは独立して管理するものは値型といいます。
int 型などの整数型、float 型などの浮動小数点型、Vector3 などの構造体型があります。

 これらの値型には、null はありません。そのため、null を代入しようとするとエラーになります。
つまり、int x = null; と書いても、代入できないのでエラーになります。また、null の状態がないので、null エラーは出ません。

 構造体もクラスと同じように自作できます。その場合には、その構造体を型として利用することが出来ます。


null 許容型


 型の宣言時に、型名の後ろに ? 演算子を利用することで、その型は null 許容という形式の型の宣言になります。



null 許容参照型


  GameObject? obj;

  string? message;

 クラスに分類されるデータ型は参照型といいます。
それぞれの固有のデータの他に、null という情報が代入出来ます。
つまり元々、クラス自体は null を代入できるのですが、それゆえに Null Reference Excepton エラーが発生します。

 そのため最近の C# では、参照型であるクラスも、? を付けているときだけ、null を代入できる機能が追加されました。
それが今回の string の null 許容参照型です。参照型であるクラスに ? を付けることで、null 許容型となります。
そしてこの機能を利用する場合、単に string と宣言した場合には、null が代入できない状態になります。

 元々 null が代入できる型であるものの、それを明示的に ? を付けたときだけ null を代入できるようにし、
それ以外では参照型であっても null を代入できないようにすることで、null チェックの処理や、
null エラー自体をなくそう、というのが、この null 許容参照型の趣旨です。

 ただし現在は、これはプレビュー機能です。採用してもいいですが、エラーまみれになります。
GameObject obj; と書いてある場合、本来なら自動的に null が代入されるのですが、それが null許容参照型からみればルール違反となるためです。
こういう方法がある、とだけ覚えておくといいでしょう。


参考サイト
MicroSoft
null 許容参照型


null 許容値型


  int? x;

  public enum StateType {
      Wait,
      Play,
      GameUp
  }

  StateType? stateType;

 構造体は値型というデータ型です。構造体には、null はありません。そのため、null を代入しようとするとエラーになります。
つまり、int x = null; と書いても、代入できないのでエラーになります。また、null の状態がないので、null エラーは出ません。

 ですが状態によっては、構造体であっても、null という値を代入して欲しいケースがあります。例えば、enum などです。
その場合、? をつけることで、本来は固有のデータしか入らない構造体に対して、null を代入出来るようになります。

 int? x = null; と書けば、本来なら数字しか入らないはずのデータ型である構造体の int 型に null を代入することが出来ます。
こちらを null 許容型(あるいは、null 許容値型)といいます。以前は null 許容型といえば値型しかなかったのですが、
C# 8.0 以降では参照型でもnull 許容ができるようになったので、区別するために両方の表現があります。


参考サイト
MicroSoft
null 許容値型


まとめ


 ここまで読んでいただくとわかるように、型の宣言時に、その型が参照型なのか、値型なのかにより、
? の持つ役割が、null 許容参照型なのか、null 許容型なのかに区別されます。

 プログラムの本質として、データの型が参照型なのか、値型なのかを理解しておかないと、この ? の部分は正確に把握出来ません。
C# のよい学習の機会になると思いますので、是非、正確な知識として処理を覚えていくようにしてください。