Different ways to check if a value is null in C#

  • Gérald Barré

In .NET there are multiple ways to check if a value is null. But all of them are not equivalent. Let's look at the different ways to check if an object is null:

object obj = ...;

obj == null;
object.Equals(obj, null);
object.ReferenceEquals(obj, null);

obj is null;          // Equivalent to ReferenceEquals(obj, null)
(object)obj == null;  // Equivalent to ReferenceEquals(obj, null)
obj is not object;    // Equivalent to !ReferenceEquals(obj, null)
obj is not {};        // Equivalent to !ReferenceEquals(obj, null)

obj.Equals(null);     // doesn't work as it would throw a NullReferenceException

There are 3 different ways to do a null check:

  • Object.ReferenceEquals(obj, null)

    ReferenceEquals returns true when the object instances are the same instance. In this case, it returns true when obj is null.

  • object.Equals(obj, null)

    Equals is similar to ReferenceEquals when one argument is null. However, the logic of this method is more complex than ReferenceEquals and is a little bit slower as the method call is not always inlined.

  • obj == null

    The == operator is similar to ReferenceEquals unless you implement the equality operator for the class. If an operator is defined, the compiler uses it instead of the default operator. In this case, the comparison logic is custom and it may not be an actual null check. You can force the compiler to use the == operator defined on object by explicitly casting the object to object.

    var obj = new Sample();
    obj == null;         // return true as it calls Sample.op_Equality which always return true
    (object)obj == null; // return false as it calls object.op_Equality (ReferenceEquals)
    obj is null;         // return false as it calls object.op_Equality (ReferenceEquals)
    
    class Sample
    {
        public static bool operator ==(Sample? a, Sample? b) => true;
        public static bool operator !=(Sample? a, Sample? b) => false;
    }

Note that is null doesn't work with structs except for Nullable<T>:

MyStruct a = default;
_ = a is null; // Compilation error
_= a == null;  // Valid only if MyStruct implements a compatible == operator

Span<char> span = default;
_ = span is null; // Compilation error
_ = span == null; // ok as Span has a compatible == operator

int? b = null;
_ = b is null; // Ok, rewritten as !b.HasValue

While is not null, is object, and is {} provide the same null check, there is a difference in the language:

if (obj is not null x) // Not valid
if (obj is object x)   // Ok, x is of type object
if (obj is {} x)       // Ok, x is of the same type as obj

#Additional resources

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?Buy Me A Coffee