Null checking with the is keyword

Why you should do null checking with is keyword instead of ==

Home DailyDrop

Daily Knowledge Drop

When checking if an instances of a object is null, the is keyword should be used instead of the double equals == operator.

This is because the == operator can be overloaded to change its meaning, while the is keyword cannot.


Comparing using ==

Consider a Person class, which contains Name and Age properties.


// define 3 person instances
Person p1 = null;
Person p2 = new Person();
Person p3 = new Person { Name = "John", Age = 33 };

if (p1 == null)
{
    Console.WriteLine($"p1 == null");
}

if (p2 == null)
{
    Console.WriteLine($"p2 == null");
}

if(p3 == null)
{
    Console.WriteLine($"p3 == null");
}

In the above example, three Person instances are defined:

  • One explicitly set to null
  • One set to a default instance of Person
  • One set with explicit values

Each of these is checked to see if they are null, using the == operator, with the output as follows:

    p1 == null
    p2 == null

Hold on... The output is showing that p2 == null is true, when p2 is clearly not null! (is was instantiated with Person p2 = new Person();) How can this be?

The reason for this, is unknown to us, the author of the Person class has overloaded the == operator to function differently to the default expected behavior.


Operator overloading

If we take a look at the contents of the Person class in full:

public class Person
{
    public string Name { get; set; }

    public int Age { get; set; }

    public static bool operator == (Person p, Person p1)
    {
        if((p?.Age == 0 && p1 is null) || (p1?.Age == 0 && p is null))
        {
            return true;
        }

        return p?.Name == p1?.Name && p?.Age == p1?.Age;
    }

    public static bool operator !=(Person p, Person p1)
    {
        return !(p?.Name == p1?.Name && p?.Age == p1?.Age);
    }
}

The == operator has been overloaded to change its meaning - Line 9 states that if either of the two Person instances being compared have an Age of 0, then no matter what, return false (meaning the two instances are not equal).

In the previous example the Person instance p2 has an Age of 0. Therefor according to the new logic for the == operator, no matter what the value of the Person being compared to, it will return false.


Comparing using is

The is operator should be used to do comparison, as it cannot be overloaded and have its definition changed:

Person p1 = null;
Person p2 = new Person();
Person p3 = new Person { Name = "John", Age = 33 };

if (p1 is null)
{
    Console.WriteLine($"p1 is null");
}

if (p2 is null)
{
    Console.WriteLine($"p2 is null");
}

if (p3 is null)
{
    Console.WriteLine($"p3 is null");
}

The output is as follows:

    p1 == null

This is the expected output, as p1 is the only instance which is truly null - the output is now accurate.


Notes

This is a small distinction between the two operators (== and is), and might not ever be an issue if you the author of the classes as well as the code using them. However in the case when using 3rd party classes, its safer to use the is keyword and ensure the code operates as expected.


References

Operator overloading

Daily Drop 38: 25-03-2022

At the start of 2022 I set myself the goal of learning one new coding related piece of knowledge a day.
It could be anything - some.NET / C# functionality I wasn't aware of, a design practice, a cool new coding technique, or just something I find interesting. It could be something I knew at one point but had forgotten, or something completely new, which I may or may never actually use.

The Daily Drop is a record of these pieces of knowledge - writing about and summarizing them helps re-enforce the information for myself, as well as potentially helps others learn something new as well.
c# .net check is