14

カスタム クラス インスタンスの比較を実装する場合、Equalsとプロパティの両方をオーバーライドする必要がありますか?GetHashCode

次のコードには、クラスのコレクションがあります。クラスは、クラスAによって比較されます。IDBCode

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

ハッシュコードは、要素が存在すると予想される「バケット」をすばやく見つけるために、ハッシュテーブルで使用されます。要素が 2 つの異なるバケットにある場合、それらが等しくないことが前提となります。

この結果、一意性を判断する目的で、ハッシュ コードを迅速なネガティブチェックとして表示する必要があります。つまり、2 つのオブジェクトが異なるハッシュ コードを持つ場合、それらは同じではありませんEquals(それらのメソッドが何を返すかに関係なく)。

2 つのオブジェクトが同じハッシュ コードを持つ場合、それらはハッシュ テーブルの同じバケットに存在します。次に、それらのEqualsメソッドが呼び出されて等しいかどうかが判断されます。

したがって、等しいと見なされる 2 つのオブジェクトに対して同じ値を返すGetHashCode 必要があります。

于 2011-05-12T17:08:33.407 に答える
8

メソッドは、メソッドDistinctを使用しGetHashCodeてアイテム間の不平等を判断し、メソッドを使用してEquals同等を判断します。

最初にハッシュ コードを使用して高速比較を行い、明らかに等しくない (ハッシュ コードが異なる) アイテムを特定します。次に、同じハッシュ コードを持つアイテムを比較して、実際に等しいアイテムを特定します。

Bクラスの実装では、 and メソッドの実装に一貫性がGetHashCodeないEqualsため、比較が正しく機能しません。2 つのBオブジェクトのハッシュ コードは異なるため、互いに比較することはできません。等しいと見なされる 2 つのアイテムは、同じハッシュ コードも返す必要があります。

IEquatable<T>クラスがインターフェースを実装する場合はメソッドが使用Equals(T)され、それ以外の場合はEquals(object)メソッドが使用されます。

于 2011-05-12T17:08:33.283 に答える
5

それらを常に一緒に、互換性のある実装でオーバーライドする必要があります。ハッシュコードの一致/不一致は、(それぞれ)「可能な等しい」および「等しくない」ことを意味します。ハッシュコード自体は等しいことを示しません。したがって、ハッシュ コードの一致が見つかった (または値のグループを作成するために使用された) 後Equalsも、一致を判断するために がチェックされます。

2 つが一致しない場合、一致するものは見つからない可能性があります。

于 2011-05-12T17:07:20.890 に答える