値がnullがどうかを確認するとき、
- ==演算子を使用した「== null」を使う方法
- is演算子を使用した「is null」を使う方法(C# 7.0以降)
の2つあります。
どちらも「値がnullか?」を判定する演算子ですが、==演算子はオーバーライドして処理を変えることができてしまうため正確なnull判定が保証されません。対してis演算子はオーバーライドできず処理をかえることができないため正確なnull判定が保証されます。
詳細は後述しますが、特別な事情が無い限りnull判定には「is null」を使うと安心です。
==演算子を使用した「== null」での判定
==演算子は「値がnullか?」を判定する演算子です。
class User
{
public string? Name { get; set; }
public User(string? name)
{
this.Name = name;
}
}
public class Program
{
static void Main(string[] args)
{
var user = new User("ひよこ");
Console.WriteLine(user == null); // False
user = null;
Console.WriteLine(user == null); // True
}
}
しかし、これは==演算子がオーバーライドされていない場合のみ有効なnull判定です。
少し乱暴ですが以下のように、==演算子をオーバーライドして「問答無用でflaseを返す」という処理へ変更にしてみます。すると、本来Trueが返ってくる場合(★)でもfalseになってしまいます。
class User
{
public string? Name { get; set; }
public User(string? name)
{
this.Name = name;
}
public static bool operator ==(User? left, User? right)
{
// 問答無用でfalseを返す!
return false;
}
public static bool operator !=(User? left, User? right)
{
// 問答無用でfalseを返す!
return false;
}
}
public class Program
{
static void Main(string[] args)
{
var user = new User("ひよこ");
Console.WriteLine(user == null); // False
user = null;
// ★本来ならTrueのはずなのに、==演算子の処理を変えているためFalseになってしまう!
Console.WriteLine(user == null); // False
}
}
つまり、==演算子を使用したnull判定は「==演算子の実装によって(意図せず)結果が変わってしまう」という危険があり、正確なnull判定が保証されません。
では正確なnull判定をするためにはどうすればいいのか。。。
ここで使うのがis演算子を使用した「is null」によるnull判定です。
is演算子を使用した「is null」での判定
is演算子は「右辺の型に変換可能か?」を判定する演算子として知られていますが、「is null」とした場合は「値がnullか?」を判定する演算子になります。
is演算子はC#言語の組み込み構文であるため、==演算子のようにオーバーライドできません。そのため正確なnull判定が保証されます。
class User
{
public string? Name { get; set; }
public User(string? name)
{
this.Name = name;
}
public static bool operator ==(User? left, User? right)
{
// 問答無用でfalseを返す!
return false;
}
public static bool operator !=(User? left, User? right)
{
// 問答無用でfalseを返す!
return false;
}
}
public class Program
{
static void Main(string[] args)
{
var user = new User("ひよこ");
Console.WriteLine(user == null); // False
user = null;
// 本来ならTrueのはずなのに、==演算子の処理を変えているためFalseになってしまう...
Console.WriteLine(user == null); // False
// is演算子を使えば正確なnull判定ができる
Console.WriteLine(user is null); // True
}
}
まとめ
==演算子はオーバーライドして処理を変更できてしまうため、正確なnull判定が保証されません。
対してis演算子はオーバーライドできず処理を変更できないため、正確なnull判定が保証できます。
状況によりけりではありますが、基本的にnull判定にはis演算子を使うと安心です。
コメント