-2

インターフェイスのGetHashCodeメソッドに関するドキュメントの「実装者への注意事項」セクションには、次のように記載されています。IEqualityComparer<T>

Equals メソッドが 2 つのオブジェクト x と y に対して true を返す場合、x の GetHashCode メソッドによって返される値が y に対して返される値と等しくなければならないことを保証する実装が必要です。

T2 つの項目が等しい場合に、 の2 つのインスタンスが同じハッシュ コードを返すようにする理由はよく知られています。それらが異なるということは、それらが等しくないことを意味しますが、それらが同じであることは、それらが潜在的に等しいことを意味します。

2 つのインスタンスが等しくない場合 (それらの値がそうであることを示唆している場合でも) 、戻り値の引用符は未定義であると解釈します。

以下を例にとります。null 以外のそれぞれがクラスの属性を表す統計的分類int?に使用したいシーケンスがあります (列挙値を考えてください)。これらの値が null の場合、トレーニング セットが欠損値に偏ってしまうため、値が等しいと見なされることは望ましくありません。どちらかといえば、この場合、他の null 値と比較して false を返す null 値が必要です。int?

問題は、GetHashCodeメソッドで null が指定された場合、おそらく 0 (または他の数値、おそらく ) を返したいことですInt32.MinValueIEqualityComparer<T>さて、この実装を使用して何かにキーを付けると、ディクショナリ内のキーの存在をチェックするパフォーマンスが最適化されないことがわかりました。

つまり、GetHashCodeが呼び出されたときに他の値と競合することがわかっている値を返すことは有効ですか? への呼び出しEqualsが false を返す場合は? 上記の引用はこの問題では定義されていないため、私はイエスに傾いています。

4

3 に答える 3

7

ほとんどすべての型で 2 つの値が存在することが絶対に必要です。v1v2

v1.Equals(v2) == false
v1.GetHashCode() == v2.GetHashCode()

... または同等のIEqualityComparer<T>. そうでない唯一のケースは、最大で 2 32 個の異なる (等しくない) 値がある場合です。それよりも多くの値があるとすぐに、鳩の穴の原則により、 ハッシュコードが再利用されます-循環するのに十分なハッシュコードがありません!

Eric Lippert のハッシュ コードに関するすばらしいブログ記事は、一読の価値があります。基本的に、あなたは正しいアイデアを持っていると思いますが、それらを強化する価値があります。

ところで、ヌルの問題は興味深いものです。例外をスローするIEqualityComparer<T>ことができますが、組み込みの実装では決してスローされないと思います。ただし、問題が1つあるように思えます-それは再帰的でなければなりません-したがって、null値はそれ自体と等しくなければなりません。それについては慎重に考える必要があるかもしれません...「異なる」null 値を表現できますか?GetHashCodeComparer<T>Equals

于 2011-10-05T05:34:32.663 に答える
2

IMO:Equalsは常にオブジェクトの等価性に関する最終的な調停者であるGetHashCodeため、等しくない値のショートカットにすぎません。GetHashCode(オブジェクトが実際に等しいかどうかに関係なく)から返された同一の値の場合はEquals、比較のために常に呼び出されます。GetHashCode等しくない値の間で競合する可能性が高いと予想されます。この動作について、あいまいな点や未定義の点は見当たりません。

于 2011-10-05T04:29:21.160 に答える
1

引用した条件が満たされている限り、任意の値を返すことができます。そうしないと、この条件に依存するクラスが正しく機能しません。

たとえば、大文字と小文字を区別しないキーによってインデックスが付けられた辞書を取り上げ、GetHashCode の実装が最初の文字の値を返すとします。したがって、「A」と「a」は同じですが、ハッシュ値が異なります (65 と 97)。言い換えれば、あなたは規則に違反しています。次に、次のようなことを行う場合:

dict["A"] = "something";
Console.WriteLine(dict["a"]);

その場合、キー "A" と "a" が等しい場合でも、2 行目は KeyNotFoundException で失敗する可能性があります。

于 2011-10-05T04:53:47.697 に答える