14

こんにちは、私は .NET でオブジェクトの GetHashCode() オーバーライドを実装するための最良の方法を調べてきましたが、私が遭遇したほとんどの回答には、数値型のメンバーから数値を何らかの方法で変更してメソッドを作成することが含まれています。問題は、英数字の文字列をキーとして使用するオブジェクトがあり、文字列をキーとしてオブジェクトの内部 ID を使用するだけで、次のような根本的な問題があるかどうか疑問に思っていることです。


// Override GetHashCode() to return a permanent, unique identifier for
// this object.
static private int m_next_hash_id = 1;
private int m_hash_code = 0;
public override int GetHashCode() {
  if (this.m_hash_code == 0)
    this.m_hash_code = <type>.m_next_hash_id++;
  return this.m_hash_code;
}

英数字の文字列をキーとして使用するオブジェクトの一意のハッシュ コードを作成するより良い方法はありますか? (いいえ、英数字文字列の数値部分は一意ではありません。これらの文字列の一部には、実際には数字がまったく含まれていません。)

4

5 に答える 5

22

GetHashCode()オブジェクトで使用する数値以外の値を呼び出すことができます。

private string m_foo;
public override int GetHashCode()
{
    return m_foo.GetHashCode();
}
于 2010-07-23T17:34:54.740 に答える
21

これは、オブジェクトのハッシュを生成するための適切なパターンではありません。

GetHashCode() の目的を理解することが重要です。これは、オブジェクトの識別プロパティの数値表現を生成する方法です。ハッシュ コードは、オブジェクトをディクショナリのキーとして使用できるようにするために使用され、場合によっては複合型間の比較を高速化します。

単純にランダムな値を生成し、それをハッシュ コードと呼ぶと、再現性がなくなります。同じキー フィールドを持つ別のインスタンスは、異なるハッシュ コードを持ち、HashSet、Dictionary などのクラスで期待される動作に違反します。

オブジェクトに識別文字列メンバーが既にある場合は、そのハッシュ コードを返すだけです。

実装者向けの MSDN のドキュメントGetHashCode()は、そのメソッドのオーバーライドを計画しているすべての人にとって必読です。

実装者への注意事項

ハッシュ関数は、オブジェクトの値に対応する数値 (ハッシュ コード) をすばやく生成するために使用されます。通常、ハッシュ関数は各タイプに固有であり、一意性のために、少なくとも 1 つのインスタンス フィールドを入力として使用する必要があります。

ハッシュ関数には、次のプロパティが必要です。

2 つのオブジェクトを比較して等しい場合、各オブジェクトの GetHashCode メソッドは同じ値を返す必要があります。ただし、2 つのオブジェクトが等しくない場合、2 つのオブジェクトの GetHashCode メソッドは異なる値を返す必要はありません。

オブジェクトの GetHashCode メソッドは、オブジェクトの Equals メソッドの戻り値を決定するオブジェクトの状態に変更がない限り、一貫して同じハッシュ コードを返す必要があります。これはアプリケーションの現在の実行にのみ当てはまり、アプリケーションが再度実行されると別のハッシュ コードが返される可能性があることに注意してください。

最高のパフォーマンスを得るには、ハッシュ関数がすべての入力に対してランダムな分布を生成する必要があります。

たとえば、String クラスによって提供される GetHashCode メソッドの実装は、同一の文字列値に対して同一のハッシュ コードを返します。したがって、2 つの String オブジェクトは、同じ文字列値を表す場合、同じハッシュ コードを返します。また、入力が特定の範囲でクラスター化されている場合でも、メソッドは文字列内のすべての文字を使用して、合理的にランダムに分散された出力を生成します (たとえば、多くのユーザーは、文字列が 128 の下位 ASCII 文字のみを含む文字列を持っている可能性があります。 65,535 の Unicode 文字のいずれかを含む)。

于 2010-07-23T17:38:41.033 に答える
2

ハッシュ コードは一意である必要はありません。Equals実装が正しければ、2 つのインスタンスに対して同じハッシュ コードを返すことは問題ありません。m_next_hash_id2 つのオブジェクトが等しい場合でも異なるハッシュ コードを持つことができるため、このロジックは壊れています。

EqualsMSDN には、およびを実装する方法に関する一連の適切な手順が記載されていGetHashCodeます。ここでの例のいくつかはGetHashCode、オブジェクトのフィールドのハッシュ コードの観点から実装されています。

于 2010-07-23T17:37:59.770 に答える
0

はい、より良い方法は、既に持っている文字列のハッシュコードを使用することです。英数字の文字列がオブジェクトのアイデンティティを定義する場合、そのハッシュコードはオブジェクトのハッシュコードに対して非常にうまく機能します。

静的フィールドをインクリメントしてハッシュコードとして使用するという考えは、悪いものです。ハッシュ コードは、可能な値の空間全体に均等に分散されている必要があります。これにより、とりわけ、ハッシュテーブルのキーとして使用されたときに適切に機能することが保証されます。

于 2010-07-23T17:35:14.637 に答える
0

GetHashCode()一般的に、インスタンスではなく値でオブジェクトを識別するものを返したいと考えています。ここでアイデアを理解している場合、メソッドはGetHashCode()、同等の値を持つ2つの異なるオブジェクトで異なるハッシュを返すことを保証すると思います。異なるインスタンスです。

GetHashCode()参照ではなく、2 つのオブジェクトの値を比較できる値を返すことを意図しています。

于 2010-07-23T17:36:14.703 に答える