比较对象时与GetHashCode相等

ser*_*hio 11 .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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是:

one A
one B
Run Code Online (Sandbox Code Playgroud)

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

one A
one B
one B+
Run Code Online (Sandbox Code Playgroud)

现在我问自己什么,因为我应该重写EqualsB类,如果它看来,这对比较没有影响?

是否GetHasCode()足以进行这种比较?

Dan*_*Tao 19

以下是您需要了解的关系Equals和之间的关系GetHashCode.

散列表使用散列码来快速找到期望存在元素的"桶".如果元素在两个不同的桶中,则假设它们不能相等.

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

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

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


Guf*_*ffa 7

Distinct方法将使用该GetHashCode方法来确定项之间的不等式,以及Equals确定相等性的方法.

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

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

如果类实现IEquatable<T>接口,Equals(T)则将使用该Equals(object)方法,否则使用该方法.


Mar*_*ell 5

你总是需要重写他们在一起,并用兼容的实现.散列码匹配/不匹配意味着(分别)" 可能的相等"和"不相等".哈希码本身并不表示相等.因此,在找到哈希码匹配(或用于创建值组)之后,Equals仍然检查以确定匹配.

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