SSteve
SSteve

Reputation: 10728

How do I avoid NullReferenceException when implementing operator==

I'm trying to implement operator== in one of my classes. According to the book Microsoft Visual C# Step by Step I should write it like so:

using System;
using System.Diagnostics;

namespace EqualTest2
{
    public class EqualTestClass
    {
        public double _x1;

        public EqualTestClass(double x1)
        {
            _x1 = x1;
        }

        public override bool Equals(object other)
        {
            if (other is EqualTestClass)
            {
                return (Math.Abs(_x1 - ((EqualTestClass)other)._x1) < 1e-6);
            }
            return false;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public static bool operator ==(EqualTestClass lhs, EqualTestClass rhs)
        {
            return lhs.Equals(rhs);
        }

        public static bool operator !=(EqualTestClass lhs, EqualTestClass rhs)
        {
            return !lhs.Equals(rhs);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            EqualTestClass test1 = new EqualTestClass(1.0);
            EqualTestClass test2 = new EqualTestClass(1.0);
            EqualTestClass test3 = new EqualTestClass(2.0);
            EqualTestClass test4 = null;

            Debug.WriteLine("1: {0}", test1 == test2);
            Debug.WriteLine("2: {0}", test1 == test3);
            Debug.WriteLine("3: {0}", test1 == test4);
            Debug.WriteLine("4: {0}", test4 == test1);
        }
    }
}

This program throws NullReferenceException on the fourth debug line because lhs is null on the line lhs.Equals(rhs). I can't put if (lhs != null) in operator== because that causes infinite recursion (as the book warns). So in order to avoid an exception when comparing a null instance of my class, I changed the implementation to this:

    public static bool operator ==(EqualTestClass lhs, EqualTestClass rhs)
    {
        try
        {
            return lhs.Equals(rhs);
        }
        catch (NullReferenceException)
        {
            return false;
        }
    }

    public static bool operator !=(EqualTestClass lhs, EqualTestClass rhs)
    {
        try
        {
            return !lhs.Equals(rhs);
        }
        catch (NullReferenceException)
        {
            return false;
        }
    }

(I'm new to C# coming from an Objective C background where [lhs method:argument] happily returns nil if lhs is nil so an exception like this would never happen.)

Is this exception-based implementation idiomatically correct C#?

Upvotes: 2

Views: 494

Answers (4)

Mr Anderson
Mr Anderson

Reputation: 2233

I would avoid using a try-catch block for your case. You need only change your operators to this:

public static bool operator ==(EqualTestClass lhs, EqualTestClass rhs)
{
    return object.Equals(lhs, rhs);
}
public static bool operator !=(EqualTestClass lhs, EqualTestClass rhs)
{
    return !object.Equals(lhs, rhs);
}

This will do the null-checking for you while still calling your overridden Equals() method. According to the source code for System.Object.Equals():

public static bool Equals(Object objA, Object objB) 
{
    if (objA==objB) {
        return true;
    }
    if (objA==null || objB==null) {
        return false;
    }
    return objA.Equals(objB);
}

Looks like that takes care of your issue.

Upvotes: 4

SpacePrez
SpacePrez

Reputation: 1086

Simply do a null test first

if(lhs == null || rhs == null){

And handle that the way you want. (return false, or maybe true if both null)

.equals() requires an object and will throw NullPointer if you try to call it on a null object. But == works fine.

Upvotes: -1

Scott Perham
Scott Perham

Reputation: 2470

Consider using ReferenceEquals(lhs, null) to check the reference for null for each of your args before checking for equality

Upvotes: 4

Luaan
Luaan

Reputation: 63732

You need to compare the arguments by reference:

if (!ReferenceEquals(lhs, null)) ...

Upvotes: 1

Related Questions