I'm trying to write an Equality Comparer for a simple class with 3 fields, like so:
public class NumberClass
{
public int A { get; set; }
public int B { get; set; }
public int C { get; set; }
}
My condition for two objects of NumberClass
to be equal is if Obj1.A == Obj2.A || Obj1.B == Obj2.B
(in other words, OR), Obj1 and Obj2 being instances of NumberClass
.
I can easily write the Equals()
of my comparer as follows, but I don't know what to do with my GetHashCode()
method.
public bool Equals(NumberClass x, NumberClass y)
{
if (x.A == y.A || x.B == y.B)
return true;
else
return false;
}
public int GetHashCode(NumberClass obj)
{
return ???
}
If my condition for equality was AND instead of OR, I could write my GetHashCode()
as follows, taken from this SO answer.
public int GetHashCode(NumberClass obj)
{
unchecked
{
int hash = 17;
if (obj != null)
{
hash = hash * 23 + obj.A.GetHashCode();
hash = hash * 23 + obj.B.GetHashCode();
}
return hash;
}
}
But that obviously wouldn't work for OR since only one of A
or B
being equal is sufficient for my equality condition to be true.
One workaround I could think of is always returning the same value in GetHashCode()
which would be sufficient for LINQ operations such as Distinct()
, but I feel like there should be another way as that has its own shortcomings.
What's the proper way to handle this situation?
P.S. For testing, imagine my Main() is the following:
static void Main(string[] args)
{
List<NumberClass> list = new List<NumberClass>();
list.Add(new NumberClass { A = 1, B = 2, C = 3 });
list.Add(new NumberClass { A = 1, B = 22, C = 33 });
var distinct = list.Distinct(new NumberComparer());
Console.ReadKey();
}
I expect distinct
to contain only the first element in the list.