关于 IEqualityComparer<T> / List<T>.Distinct() 的问题

5

这是我刚刚编写的相等比较器,因为我想从包含实体的列表中获取不同的项目。

    class InvoiceComparer : IEqualityComparer<Invoice>
    {
        public bool Equals(Invoice x, Invoice y)
        {
            // A
            if (Object.ReferenceEquals(x, y)) return true;

            // B
            if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) return false;

            // C
            return x.TxnID == y.TxnID;
        }

        public int GetHashCode(Invoice obj)
        {
            if (Object.ReferenceEquals(obj, null)) return 0;
            return obj.TxnID2.GetHashCode();
        }
    }
  1. 为什么Distinct需要一个比较器而不是Func<T,T,bool>
  2. (A)和(B)除了优化之外还有别的作用吗?在比较引用时,因为微妙的差异,是否存在它们无法按预期方式运作的情况?
  3. 如果我想要,我能用以下代码替换(C)

    return GetHashCode(x) == GetHashCode(y)


随机自夸观察:这可能是一个不错的考试题目。 - Aaron Anodide
3个回答

4
  1. 因此,它可以使用哈希码使其为O(n),而不是O(n2)。
  2. (A)是优化。
    (B)是必须的;否则,它会抛出NullReferenceException。 然而,如果Invoice是一个结构体,它们都是不必要的且更慢
  3. 不。 哈希码不是唯一的

我的大脑不太灵光,我曾经以为在文档中读到过“相等的对象返回相等的哈希码”这句话... - Aaron Anodide

1
  • A 是确保两个位于同一内存地址的对象引用同一个对象的简单快捷方式。
  • B - 如果其中一个引用为 null,则显然没有进行相等比较的意义。
  • C - 不是,有时 GetHashCode() 可以为不同的对象返回相同的值(哈希冲突),因此您应该进行相等比较。

关于不同对象具有相同哈希码值的情况,MSDN

如果两个对象比较相等,则每个对象的 GetHashCode 方法必须返回相同的值。但是,如果两个对象不相等,则两个对象的 GetHashCode 方法不必返回不同的值。


0

Distinct() 基本上是基于“不相等”的概念工作的。因此,如果您的列表包含非原始类型,则必须实现自己的EqualityComparer。

在 A 部分,您可以检查对象是否相同。如果两个对象相等,则它们不必相同,但如果它们相同,则可以确定它们是相等的。因此,在某些情况下,A 部分可以提高该方法的效率。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接