Different ways to check if a value is null in C#
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
returnstrue
when the object instances are the same instance. In this case, it returnstrue
whenobj
is null.object.Equals(obj, null)
Equals
is similar toReferenceEquals
when one argument isnull
. However, the logic of this method is more complex thanReferenceEquals
and is a little bit slower as the method call is not always inlined.obj == null
The
==
operator is similar toReferenceEquals
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 onobject
by explicitly casting the object toobject
.C#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!