【C#】null判定には「is演算子」を使うと安心!「== null」と「is null」の違い。

値が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演算子を使うと安心です。

コメント