比较对象时与GetHashCode相等

时间:2011-05-12 16:30:08

标签: .net comparison equals gethashcode

在实现自定义类实例比较时,我们应该覆盖EqualsGetHashCode属性吗?

在下面的代码中,我有一组类。课程A ID ,课程B - Code 进行比较。

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()是否足以胜任这种比较?

3 个答案:

答案 0 :(得分:15)

以下是您需要了解EqualsGetHashCode之间关系的内容。

散列表使用散列码快速查找预期存在元素的“桶”。 如果元素位于两个不同的桶中,则假设它们不能相等。

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

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

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

答案 1 :(得分:6)

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

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

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

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

答案 2 :(得分:5)

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

如果两人不同意,你可能永远找不到匹配。