C# 泛型引用相等比较器不适用于ValueTuple

C# 泛型引用相等比较器不适用于ValueTuple,c#,generics,iequalitycomparer,valuetuple,C#,Generics,Iequalitycomparer,Valuetuple,我已经编写了一个通用的相等比较器,无论参数类型的GetHashCode和Equals方法看起来如何,它都应该通过引用进行比较: public class ReferenceEqualityComparer<T> : IEqualityComparer<T> { public static ReferenceEqualityComparer<T> Inst = new ReferenceEqualityComparer<T>(); p

我已经编写了一个通用的相等比较器,无论参数类型的
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); }
}
但是这个比较器的行为并不像预期的那样,所以我猜我做错了什么。要想看出什么是错的,首先考虑以下情况:

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
然后输出改变:

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
相同,并且在两个
(object,object)
上使用
ReferenceEquals
是否与在
项1
项2
上使用
ReferenceEquals
相同?和
GetHashCode
类似吗

ReferenceEquals和object.Equals不一样吗

不,不是
object.Equals
将对第一个操作数使用虚拟分派,查找对象的实际运行时类型的
Equals
的实现,并使用该类型的定义所说的任何操作。对于
ValueTuple
,它将比较两个元组的实际值
ReferenceEquals
只是比较引用并告诉您它们是否相等。在这种特殊情况下,您有两个不同的引用,即使每个引用引用的值相同

在两个(对象,对象)上使用ReferenceEquals与在Item1s和Item2s上使用ReferenceEquals以及对结果进行&&ing不是一样吗

不,不是。它只会告诉你传入的两个对象是否都是对同一个对象的相同引用。他们不会检查这些对象的实际值。在本例中,有两个不同的引用,因此它们不相等

和GetHashCode类似

这是类似的,因为第一个版本使用的是
ValueTuple
实现,该实现基于元组中项目的值计算哈希,而第二个版本完全基于对对象本身的引用来计算哈希,因此当您对两个不同对象有两个不同的引用时,但是,当这些对象内部具有相等值时,第一个对象认为它们相等,第二个对象认为它们不相等

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