When I write this:
ReferenceEquals(x, null)
Visual studio suggests that the
null check can be simplified.
They mean the same in this case, yes. Most would use x == null
though.
I guess ReferenceEquals
could be little bit confusing because actually null
is a literal that means no reference at all. How can any reference be equal to no reference?
Note that x is null
is only allowed with C#7 and it's pattern matching feature. Normally you use is
to check if x
is a compatible type but null
is not a type. So this is a bit confusing as well.
That's why i prefer x == null
I noticed a lot of answers specifying that x == null
, x is null
, and ReferenceEquals(x, null)
are all equivalent - and for most cases this is true. However, there is a case where you CANNOT use x == null
as I have documented below:
Note that the code below assumes you have implemented the Equals method for your class:
Do NOT do this - the operator == method will be called recursively until a stack overflow occurs:
public static bool operator ==(MyClass x1, MyClass x2)
{
if (x1 == null)
return x2 == null;
return x1.Equals(x2)
}
Do this instead:
public static bool operator ==(MyClass x1, MyClass x2)
{
if (x1 is null)
return x2 is null;
return x1.Equals(x2)
}
Or
public static bool operator ==(MyClass x1, MyClass x2)
{
if (ReferenceEquals(x1, null))
return ReferenceEquals(x2, null);
return x1.Equals(x2)
}
I realize that I'm supre-late to the party and that answers have been given, but I feel the need to summarize a bit since this is a thing I search for every 8-12 months or so and I'd like to have an explanation I can understand (hopefully, if it gets posted)..
This is the tried and tested method to perform a safe reference equality comparison. It basically performs (object)a == (object)b
(or something to that effect) and has the advantages that its use is instantly recognizable and it can't be overridden.
This method is the one that feels "natural" to most people (since most comparison done throughout C# will be done with this operator).
Default behaviour on reference types should be correct. However, this can be overloaded, which can lead to unexpected results (imagining a failed implementation of the operator overload).
Like @mdebeus said, an additional risk (however marginal even for a competent monkey that read a primer on C#) is causing a StackOverflowException
. This can appear when overloading == and != and using the operators inside the method itself.
OK so this is shiny new sort of sugary thing that we get. Microsoft describes is in this case with:
The is operator checks if the runtime type of an expression result is compatible with a given type.
[...]
The E is T expression returns true if the result of E is non-null and can be converted to type T by a reference conversion, a boxing conversion, or an unboxing conversion; otherwise, it returns false. The is operator doesn't consider user-defined conversions.
(read a complete description here)
The short of it is that this will return true if a can be converted through b via boxing, unboxing or covariance. As you would expect, this works very well against null.
All in all, as a personal note, although is makes things shorter and prettier for null check in equality overloading, I think I'll would still use ReferenceEquals, simply because I'm a control-freak and there is at least a part of how is works that worries me when it comes to cases of covariance.
Are those really the same?
Semantically yes (assuming x
is not a value type). You're doing a null check which is the same for all reference types.
Implementation: no. x == null
or x is null
will be directly implemented as IL instructions but Object.ReferenceEquals(x, null)
will be a method call.1
Also note if the type of x
has overridden operator ==
then x == null
may not be equivalent (changing the semantics of null checks in an operator overload is, at best, poor code because no one expects such a semantic change).
1 Of course the optimiser could recognise this and just output the IL, you'll need to look at the IL to confirm this.