Short version: For well-behaved types, there is no difference between foo is null
and foo == null
.
Long version:
When you write foo == null
and an appropriate overload of operator ==
exists, then that's what is called. Otherwise, reference equality is used for reference types and value equality is used for value types.
When you write foo is null
for a reference type, this is compiled as if you wrote object.Equals(null, foo)
(notice the switched order, it makes a difference). In effect, this performs reference equality comparison between foo
and null
. For a value type, foo is null
does not compile.
This means that if you write a class with operator ==
that says that some instance of foo
is equal to null
, then foo == null
will give different result than foo is null
.
An example showing this:
using System;
public class Foo
{
public static void Main()
{
var foo = new Foo();
Console.WriteLine(foo == null);
Console.WriteLine(foo is null);
}
public static bool operator ==(Foo foo1, Foo foo2) => true;
// operator != has to exist to appease the compiler
public static bool operator !=(Foo foo1, Foo foo2) => false;
}
This code outputs:
True
False
When you overload operator ==
, you should make it behave in a reasonable way, which, among other things, means you should not say that foo == null
is true
for non-null
foo
. As a side effect of this, under normal circumstances, foo == null
and foo is null
will have the same value.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…