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"