C# 8 あたりから導入される null 安全について
C# 8 あたりからnull安全が導入される予定だそうです。
C# では値型(intやstructなど)はnull値は取れません。
値型でnull値をとるにはnull許容値型(int?など?をつける)を使います。
一方、参照型(stringやclassなど)はデフォルトでnull許容型であり、null値の許容、非許容が区別されていません。
ですので、以下のコードはコンパイルが通りますが、ユーザーオブジェクトを取得するTryGetUserメソッドが実行時にnullを返した場合、user.Nameはnull参照例外をスローします。
var user = TryGetUser(id);
string name = user.Name; // => user が null なら System.NullReferenceException
参照型でもnull許容、null非許容の区別が付くようになった場合、null参照例外が発生するコードはコンパイル時に検出してくれるようになります。
つまり、実行時にnull参照例外がスローされる心配がなくなります。
null安全が導入されると、コード上でnullかどうかを判断し処理を分岐させる必要が出てきますが、if文などの条件分岐を使うと冗長になります。
var user = TryGetUser(id);
if (user == null)
return;
string name = user.Name
そこで、既にある??(null合体演算子)、?. ?[](null条件演算子)を使用すると簡潔に書くことができるようになります、
参考:null安全とは、何が嬉しいのかについて
参考:C# におけるnull参照問題について
??(null合体演算子)
??はnull合体演算子やnullカスケード演算子と呼ばれます。
左辺がnullでない場合は左辺を返し、nullである場合は右辺を返します。
下記のコードは、TryGetUserがnullを返した場合、右辺のDefaultUserが評価されます。
User user = TryGetUser(id) ?? DefaultUser();
?. ?[](null条件演算子)
?. ?[]はnull条件演算子と呼ばれています。
?. ?[]はメンバーやインデックスのアクセスの前に、左辺がnullかどうかテストしnullでない場合、アクセスが行われます。
左辺がnullの場合、nullが返ります。
下記のコードはuserがnull出ない場合、Nameの値が返り、nullの場合にはnullを返します。
userがnullでもNullReferenceExceptionは発生しません。
var name = user?.Name;
また下記のコードもusers(Userのコレクションを想定)がnullでもNullReferenceExceptionが発生しません。
var second = users?[1];
if文や?:(三項演算子)を使った場合に比べて読みやすいと思います。
// if 文
string name;
if (user != null) name = user.Name;
// 三項演算子
var name = (user == null) ? null : user.Name;
?. ??の合わせ技
?. ?? を組み合わせて使うこともできます。
userがnullの場合、"名無しの権兵衛"、nullでない場合Nameの値が返ります。
var user = TryGetUser();
string name = user?.Name ?? "名無しの権兵衛"
??=(null合体代入演算子)
2019/05/23追記。
string name1 = null;
name1 ??= "NULLのときの名前";
Console.WriteLine(name1); // "NULLのときの名前"
string name2 = "nossa";
name2 ??= "NULLのときの名前";
Console.WriteLine(name1); // "nossa"