14

在实现自定义类实例比较时,我们是否应该同时覆盖Equals和属性?GetHashCode

在下面的代码中,我有一个类的集合。类A是比较的ID,类是比较BCode

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            List<I> bars = new List<I>();
            bars.Add(new A() { Id = 1, Code = "one A" });
            bars.Add(new B() { Id = 1, Code = "one B" });
            bars.Add(new A() { Id = 1, Code = "one A+" });
            bars.Add(new B() { Id = 1, Code = "one B" }); // Code = "one B+"

            var distictBars = bars.Distinct();

            foreach (var item in distictBars)
            {
                Debug.WriteLine(item.Code);
            }
        }
    }

    interface I
    {
        string Code { get; set; }
    }

    class A : I, IEquatable<A>
    {
        public int Id { get; set; }
        public string Code { get; set; }

        public bool Equals(A other)
        {
            // this is the ??? comparison
            return this.Id == other.Id;
            //return this.Code == other.Code;
        }

        public override bool Equals(object obj)
        {
            if (obj is A)
                return this.Equals(obj as A);
            else
                return object.ReferenceEquals(this, obj);
        }

        public override int GetHashCode()
        {
            // this is the wanted comparison
            return this.Id;
        }
    }

    class B : I, IEquatable<B>
    {
        public int Id { get; set; }
        public string Code { get; set; }

        public bool Equals(B other)
        {
            // this is the ??? comparison
            return this.Id == other.Id;
        }

        public override bool Equals(object obj)
        {
            if (obj is B)
                return this.Equals(obj as B);
            else
                return object.ReferenceEquals(this, obj);
        }

        public override int GetHashCode()
        {
            // this is the wanted comparison
            return this.Code.GetHashCode();
        }
    }
}

输出是:

one A
one B

如果评论Code = "one B+"的输出是

one A
one B
one B+

现在我问自己,如果这似乎对比较没有影响,我应该Equals在课堂上覆盖什么?B

GetHasCode()对于这种比较来说,压倒一切是否足够?

4

3 回答 3

23

这是您需要了解的有关 和 之间关系的Equals内容GetHashCode

哈希表使用哈希码来快速找到一个“桶”,其中预计存在一个元素。如果元素位于两个不同的桶中,则假设它们不能相等。

这样做的结果是,为了确定唯一性,您应该将哈希码视为快速否定检查:即,如果两个对象具有不同的哈希码,则它们是相同的(无论它们的Equals方法返回什么)。

如果两个对象具有相同的哈希码,它们将驻留在哈希表的同一个桶中。然后Equals将调用它们的方法来确定相等性。

因此,GetHashCode 必须为您希望被视为相等的两个对象返回相同的值。

于 2011-05-12T17:08:33.407 回答
8

Distinct方法将使用该GetHashCode方法来确定项目之间的不等式,并使用该Equals方法来确定相等性。

它首先使用哈希码进行快速比较以确定哪些项目肯定不相等,即具有不同的哈希码,然后比较具有相同哈希码的项目以确定哪些项目真正相等。

在类的实现中, and方法B的实现不一致,因此比较将无法正常工作。您的两个对象具有不同的哈希码,因此不会相互比较。被认为相等的两个项目也应该返回相同的哈希码。GetHashCodeEqualsB

如果一个类实现了IEquatable<T>接口,则使用该方法Equals(T),否则使用该Equals(object)方法。

于 2011-05-12T17:08:33.283 回答
5

您总是需要一起覆盖它们使用兼容的实现。哈希码匹配/不匹配意味着(分别)“可能相等”和“不相等”。哈希码本身并不表示相等。因此,在找到哈希码匹配(或用于创建值组)后,Equals仍会检查以确定匹配。

如果两者不一致,您可能永远找不到匹配项。

于 2011-05-12T17:07:20.890 回答