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