0

我编写了一个通用的相等比较器,无论参数类型的GetHashCodeEquals方法看起来如何,它都应该通过引用进行比较:

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(在这种情况下是一对objects):

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,因此将使用默认比较器。这意味着,两者都Item1Item2使用引用相等和默认哈希码(地址或其他东西)。输出是我所期望的。

但如果我改为使用比较器

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.EqualsReferenceEquals(object,object)ReferenceEqualsItem1Item2&&GetHashCode

4

1 回答 1

1

ReferenceEquals 和 object.Equals 不一样吗

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

在两个(对象,对象)上使用 ReferenceEquals 是否与在 Item1s 和 Item2s 上使用 ReferenceEquals 以及 &&ing 结果相同?

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

和 GetHashCode 类似吗?

这是类似的,因为第一个版本使用ValueTuple基于元组中项目的值计算散列的实现,而第二个版本完全基于对对象本身的引用计算散列,所以当你有两个不同的对两个不同对象的引用,但是如果这些对象但这两个对象在内部具有等效值,则第一个认为它们相等,第二个认为它们不相等。

于 2017-10-05T19:20:16.793 回答