I have written a generic equality comparer that should always compare by reference, no matter how the GetHashCode
and Equals
methods of the parameter type look like:
public class ReferenceEqualityComparer<T> : IEqualityComparer<T>
{
public static ReferenceEqualityComparer<T> Inst = new ReferenceEqualityComparer<T>();
private ReferenceEqualityComparer() { }
public bool Equals(T x, T y) { return ReferenceEquals(x, y); }
public int GetHashCode(T obj) { return RuntimeHelpers.GetHashCode(obj); }
}
I threw in a ValueTuple
(in this case a pair of object
s) like so:
var objectPairComparer = ReferenceEqualityComparer<(object,object)>.Inst;
But this comparer does not behave as expected, so I guess I am doing something wrong. To see what's wrong, first consider the following situation:
object a = new object();
object b = new object();
object c = a;
object d = b;
HashSet<(object, object)> set = new HashSet<(object, object)>();
Console.WriteLine("set.Add((a, b)) = " + set.Add((a, b))); // returns true
Console.WriteLine("set.Contains((c, d)) = " + set.Contains((c, d))); // returns true
Console.WriteLine("set.Add((c, d)) = " + set.Add((c, d))); // returns false
Since no comparer is given as input to the HashSet
, the default comparer will be used. That means, both Item1
and Item2
will use reference equality and default hash code (the address or something). The output is what I expect.
But if I instead use the comparer
HashSet<(object,object)> set = new HashSet<(object,object)>(objectPairComparer);
then the output changes:
Console.WriteLine("set.Add((a, b)) = " + set.Add((a, b))); // returns true like before
Console.WriteLine("set.Contains((c, d)) = " + set.Contains((c, d))); // returns FALSE
Console.WriteLine("set.Add((c, d)) = " + set.Add((c, d))); // returns TRUE
But they should behave the same way! Why don't they? Isn't ReferenceEquals
the same as object.Equals
, and isn't ReferenceEquals
used on two (object,object)
the same as using ReferenceEquals
both on the Item1
s and Item2
s and &&
ing the results? And GetHashCode
analogous?