C#: Why You Should Prefer the is Keyword Over the == Operator
In the previous blog post you learned about different ways to do a null check. The traditional way is to use the ==
operator:
if(person == null) { }
Since C# 7, you can use the is
keyword to do a null check:
if(person is null) { }
The is
keyword has the big advantage that it ignores any operator overloads that are defined on the class of the instance you want to check. When you use the ==
operator, it could be possible that this operator is overloaded and you get an unexpected result. Let’s look at a simple example.
The following code snippet shows the Main
method of a .NET Console app. At the beginning, a person
variable of type Person
is declared, and it is initialized with null
. Then the results of person == null
and person is null
are written to the Console.
static void Main(string[] args)
{
Person person = null;
Console.WriteLine("Is Person null?");
Console.WriteLine($"== says: {person == null}");
Console.WriteLine($"is says: {person is null}");
}
public class Person
{
...
}
What do you think is the output of the code above?
Obviously, you might think that this is written to the Console:
Is Person null?
== says: True
is says: True
But actually, what you can definitely say from the code above is that person is null
definitely returns true
, as the person
variable actually is null
.
But you can’t say whether person == null
returns true
or false
without seeing the content of the Person class. If the Person
class overloads the ==
operator, it can do whatever it wants.
Let’s just create a hacked Person
class like below. As you can see, it overloads the ==
operator and it just returns false:
public class Person
{
public static bool operator ==(Person x, Person y)
{
return false;
}
public static bool operator !=(Person x, Person y)
{
return !(x == y);
}
public override bool Equals(object obj)
{
return base.Equals(obj);
}
}
When you run now the Console app, you will see this output:
Is Person null?
== says: False
is says: True
The is
keyword is still right, as the person
variable is actually null
, but the overloaded operator returns a result that you wouldn’t expect.
So, choose wisely in your code. If you want to do a proper null
check, the is
keyword is the way to go.
Once you get used to it, it starts looking quite nice in your code.
Comments (13)
[…] C#: Why You Should Prefer the is Keyword Over the == Operator (Thomas Claudius Huber) […]
> “The is keyword is still right, as the person variable is actually null, but the overloaded operator returns a result that you wouldn’t expect.”
well if implementation of == somehow differs, then it should be written in documentation, therefore you should expect it ¯\_(ツ)_/¯
(like for example in Unity)
Thought it is a problem in case of missing documentation or when users didnt read it.
Hey Henrich,
good point with the documentation. But aren’t nearly all problems a case of missing documentation or a case where users didn’t read it? :-)
I think the advantage of “is” is that you don’t have to read any docs, you just know what it does.
It’s worth noting that both the null coalescing operator (??) and the null coalescing assignment operator (??=) behave like the is statement, safely ignoring the overridden ‘==’ operator.
Nice article and thanks for blowing my mind on this Sunday morning ;-).
Hi Patrice,
yes, that’s correct, Null coalescing operator ?? does always a proper null check, no matter if the == operator is overwritten or not.
Thanks for the great feedback.
Have a nice Sunday! :-)
Thomas
Good note! Thank you Patrice.
!= operator is it not overloadable, if it is then you will have the same situation, then is there a ‘is not’ keyword in C# language
I just figured you could use !(obj is null) but looks ugly compared to (obj != null)
Yes, exactly. !(obj is null) is the way to go. (obj is object) should also work. :)
Hi Thomas,
I have just stumbled upon a special case where the compiler seams to be happy with it, but will have the “nice” effect of throwing an error at runtime.
If T is a reference everything is just fine, but if T is a ValueType then this part will throw an Exception:
if (default(T) is not null) { … }
Originally the code looked like:
if (default(T) != null) { … }
and this works for all cases.
I forgot to mention that T is a generic type.
Hi Radusun, yes, that’s a great example where we still need to be careful. :) Thanks for sharing.
Could you explain a little bit more. I’ve tried
Console.WriteLine(TClass.M());
Console.WriteLine(TClass.M());
Console.WriteLine(TClass.M());
public static class TClass
{
public static string M()
{
if (default(T) is not null)
{
return “default is not null”;
}
return “default is null”;
}
}
and there is no exception