25

Consider the following class:

public class Code : IEquatable<Code> 
{
    public string Value { get; set; }

    public override bool Equals(object obj)
    {
         return Equals(obj as Code);
    }

    public override bool Equals(Code code)
    {
         if (code == null) return false;
         return this.Value == code.Value;
    }

    public static bool operator ==(Code a, Code b)
    {
         if (a == null) return b == null;
         return a.Equals(b);
    }

    public static bool operator !=(Code a, Code b)
    {
         if (a == null) return b!= null;
         return !a.Equals(b);
    }

    // rest of the class here
}

Now try using the == method:

Code a = new Code();
Code b = new Code();
Console.WriteLine("The same? {0}", a==b);

The result is a StackOverflowException because the == method calls itself when it checks for null.

But if I take out the null check:

public static bool operator ==(Code a, Code b)
{
    return a.Equals(b);
}

I get a NullReferenceException!

What's the correct way to define these methods?

MCS
  • 22,113
  • 20
  • 62
  • 76

3 Answers3

34

You can also use (object)a == null

Rex M
  • 142,167
  • 33
  • 283
  • 313
  • 1
    There is an alternative to this solution that currently has more upvotes, so let me note that `(object)a == null` results in faster code, to the extent that a `ReferenceEquals` op== implementation took more than twice as long as the equivalent using `(object)a == null`. If you use the same code also for `Equals`, this can have a knock-on effect in every `Distinct()`, `Dictionary<>`, `HashSet<>`, `ToLookup` etc. you use with this type as the key. – Eamon Nerbonne May 29 '14 at 11:18
  • 1
    A Linqpad microbenchmark for those interested in replicating the perf problem with `ReferenceEquals`: https://github.com/EamonNerbonne/ValueUtils/blob/master/NullCheckBenchmark.linq. Note that apparently sometimes the CLR does inline it, so if you're lucky it won't matter. – Eamon Nerbonne May 29 '14 at 12:30
22

use System.Object.ReferenceEquals(a, null)

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
2

Starting in C# 7, you can simply use the is keyword to do a direct reference comparison. See Thorkil's answer to What is the difference between “x is null” and “x == null”?

Malcolm
  • 510
  • 3
  • 5
  • 19