基本的に、私はこれまで、次のいる:複雑な等価性のためにObject.GetHashCode()を実装するにはどうすればよいですか?
class Foo {
public override bool Equals(object obj)
{
Foo d = obj as Foo ;
if (d == null)
return false;
return this.Equals(d);
}
#region IEquatable<Foo> Members
public bool Equals(Foo other)
{
if (this.Guid != String.Empty && this.Guid == other.Guid)
return true;
else if (this.Guid != String.Empty || other.Guid != String.Empty)
return false;
if (this.Title == other.Title &&
this.PublishDate == other.PublishDate &&
this.Description == other.Description)
return true;
return false;
}
}
ので、問題はこれです:私は、一意の識別子である非必須フィールドGuid
を、持っています。これが設定されていない場合は、2つのオブジェクトが等しいかどうかを判断する試みとして、精度の低いメトリックに基づいて同等性を判断する必要があります。これはうまく動作しますが、それはGetHashCode()
汚いです...どうすればいいですか?素朴な実装は、次のようなものになります。
public override int GetHashCode() {
if (this.Guid != String.Empty)
return this.Guid.GetHashCode();
int hash = 37;
hash = hash * 23 + this.Title.GetHashCode();
hash = hash * 23 + this.PublishDate.GetHashCode();
hash = hash * 23 + this.Description.GetHashCode();
return hash;
}
しかし、2種類のハッシュの衝突の可能性はありますか?確かに、私はそれが1 in 2 ** 32
であるとは思わないでしょう。これは悪い考えですか、もしそうなら、どうすればいいでしょうか?
ハッシュアルゴリズムが均等であることよりも等価アルゴリズムに合致することが重要です。ハッシュの目的は、ハッシュテーブル内でまともな分布を得ることだけであることを覚えておいてください。 1つの特定のバケツに大規模に歪んでいない限り、オッズはうまくいくでしょう。あなたが懸念している場合は、あなたのオブジェクトの消費者が遭遇する可能性のある妥当なシナリオを選びます。たとえば、合理的であれば数百個を辞書に入れておきます。結果。 –
私が実際に見たことのあるものは〜200でしたが、典型的な使用は<30であり、あなたはおそらく正しいでしょう。 –
ヘックは30項目以下で、リンクリストの線形検索はおそらく合理的に実行可能です。常に0のハッシュコードを返すことができ、衝突の可能性が100%あり、許容できるパフォーマンスを得ることができます。ハッシュコードの分布が良好であるという点は、辞書のサイズが大きくなるとパフォーマンスが向上することです。テーブルに小さな数のアイテムしか置かない場合は、厄介なディストリビューションを持ち、良い結果を得ることができます。 –