我编写了一个通用的相等比较器,无论参数类型的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
相同&&
s和GetHashCode
s以及Prelude> (i, j) = (3, 4)
Prelude> (i, j) = (j, i)
Prelude> i
结果?和4
类似吗?
答案 0 :(得分:1)
ReferenceEquals与object.Equals
不同
不,不是。 object.Equals
将在第一个操作数上使用虚拟分派,为对象的实际运行时类型找到Equals
的实现,并使用该类型定义所要执行的任何操作。在ValueTuple
的情况下,它将比较两个元组的实际值。 ReferenceEquals
只是比较引用并告诉您它们是否相等。在这种特殊情况下,您有两个不同的引用,即使每个引用引用的值相同。
不是在两个(对象,对象)上使用的ReferenceEquals与在Item1s和Item2s上使用ReferenceEquals以及&amp;&amp; ing结果相同吗?
不,不是。它只是 会告诉您传入的两个对象是否都是同一个对象的相同引用。他们不会检查这些对象的实际值。在这种情况下,您有两个不同的引用,因此它们不相等。
和GetHashCode类似吗?
这是类似的,因为第一个版本使用ValueTuple
实现,它根据元组中项的值计算哈希值,而第二个版本完全根据对象的引用计算哈希值本身,所以当你对两个不同的对象有两个不同的引用,但是那些对象但是那两个对象在内部具有等价值的地方,第一个认为它们相等,第二个认为它们是不相等的。