Unityでnull許容参照型を使ってみた
Unityでもnull許容参照型。どう書くか好みの別れそうな部分があったので、個人的な方針。
Unity 2021.1.7f1。
1.どう有効にするか
コンパイラオプションでプロジェクト全体を有効にできるけど、それではアセットのコードなんかも影響して警告を出し始めるのでちょっとやってらんない。
対応
ファイルごとに#nullable enable
を書く方式でやります。(まあusing
だって毎回やってることですし。)
2.Unityのnullチェックでは警告が出る問題
UnityEngine.Object
のnullチェックはコンパイラが追えず、チェック後も警告が出てしまう。
対応
!
演算子を使う。
if (hoge) // Unityはnullチェックをこう書けるが { hoge.Piyo(); // 警告が出る。 } if (fuga) { fuga!.Piyo(); // !演算子を使えば警告は出ない。 }
3.Linqはちょっと不便なところがある
たとえばWhere
でnullチェックを行っても、null許容型が非nullになったりはしない。
ついでにToArray()
の戻り値はnull許容型。
対応
!
演算子を使う。
List<string?> list; var array1 = list.Where(_ => _ != null).ToArray(); //string?[]?型 var array2 = list.Where(_ => _ != null).Select(_ => _!).ToArray()!; //string[]型
4.GetComponentキャッシュ書き方
Text? text; Text Text => text ? text! : text = GetComponent<Text>();
5.SerializeField フィールドは非nullにするのが丸い
SerializeField
の配列やクラスはUnityの仕様上null
にならない。なので非null指定にしてしまうのがよさげ。
対応
default!
で初期化する。
[SerializeField] int[] array = default!; [SerializeField] int[] array = new int[0]; // これでも良い。 [SerializeField] int[] array = default; // これは警告がでる [SerializeField] int[]? array = default; // 警告はでないけど、せっかくだから非null指定したい。
6.SerializeField オブジェクト参照で非null指定したいケース
SerializeField
で参照しているコンポーネントなどがnullかどうかはユーザーの設定次第。よってnull許容にするのが自然。
なんだけど、値が入ってないとエラーにするしかないコアな部分なら、非null指定にしても支障はない。
対応
必須のフィールドなら非null指定にする。
// 動作に必要なフィールドは非nullにしてしまう [SerializeField] GameObject prefab = default!; // nullでも動くならnull許容型にする。 [SerializeField] AudioClip? sound = default;
7.ジェネリクスはどうしようもない場合がある
参照型か値型かの制限が要る。これはcsharpのバージョンアップを待つことになりそう。
対応
諦めて#nullable disable
する。