I'm trying to implement the IEquatable<T>
interface and ==
operator. The implementation below triggers a NullReferenceException
when I try to use the ==
operator despite the fact that both operands are non-null. I've added comments to the minimum example code to show exactly where the exception occurs. What am I doing wrong?
using System;
namespace scratchpad
{
class TestClass : IEquatable<TestClass>
{
public int data;
public TestClass(int d)
{
this.data = d;
}
public bool Equals(TestClass other)
{
if (other == null)
return false;
else
return this.data == other.data;
}
public override bool Equals(object other)
{
if (other is TestClass)
return this.Equals((TestClass)other);
else //Includes null
return false;
}
public override int GetHashCode()
{
return this.data;
}
public static bool operator ==(TestClass left, TestClass right)
{
return left.Equals(right); //This line triggers the NullReferenceException
}
public static bool operator !=(TestClass left, TestClass right)
{
return !left.Equals(right);
}
}
class Program
{
static void Main(string[] args)
{
TestClass tc1 = new TestClass(10);
TestClass tc2 = new TestClass(10);
Console.WriteLine("tc1="+tc1.data); //Prints "tc1.data=10" fine
Console.WriteLine("tc1="+tc1.data); //Prints "tc2.data=10" fine
bool isEqual = tc1 == tc2; //NullReferenceException occur here
Console.WriteLine("isEqual="+isEqual); //Never gets to here
}
}
}
Edit (to clarify question in response to duplicates question flags):
I am not asking what a NullReferenceException
is (I understand that) and I am not interested in ReferenceEquals
as I need to equate the object's values.
Actually, your overloaded equality operator is hit three times:
First, when called from Program.Main(string[])
with the line tc1 == tc2
, where left
=tc1
and right
=tc2
, which then calls TestClass.Equals(TestClass)
where other
=tc2
.
From there, other == null
now calls your overloaded equality operator a second time, where left
=tc2
and right
=null
.
Now, TestClass.Equals(TestClass)
is called also a second time, where other
=null
.
And finally, other == null
calls your overloaded equality operator for a third time, where both left
=null
and right
=null
. This now eventually causes the System.NullReferenceException because left was null.
To fix this coding error, replace other == null
with other is null
in TestClass.Equals(TestClass)
:
public bool Equals(TestClass other)
{
if (other is null)
return false;
else
return data == other.data;
}
Alternatively, as conditional expression (using expression body):
public bool Equals(TestClass other) => !(other is null) && data == other.data;