我编写了一个通用的相等比较器,无论参数类型的GetHashCode
和Equals
方法看起来如何,它都应该通过引用进行比较:
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); }
}
我像这样扔了一个ValueTuple
(在这种情况下是一对object
s):
var objectPairComparer = ReferenceEqualityComparer<(object,object)>.Inst;
但是这个比较器的行为并不像预期的那样,所以我想我做错了什么。要查看问题所在,首先考虑以下情况:
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
由于没有比较器作为 的输入HashSet
,因此将使用默认比较器。这意味着,两者都Item1
将Item2
使用引用相等和默认哈希码(地址或其他东西)。输出是我所期望的。
但如果我改为使用比较器
HashSet<(object,object)> set = new HashSet<(object,object)>(objectPairComparer);
然后输出改变:
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
但他们应该以同样的方式行事!他们为什么不呢?和,不ReferenceEquals
一样吗_ _ _ _ 和类似的?object.Equals
ReferenceEquals
(object,object)
ReferenceEquals
Item1
Item2
&&
GetHashCode