2009-09-10 1 views
12

私は多くの目的のために辞書(TKey、TValue)を使用しました。しかし、私はキーがintやstringのような主な型であったので、私が信じているGetHashCode()を実装するためのシナリオに遭遇していません。 私は1つのキーのカスタムオブジェクトを使用するため、GetHashCodeメソッドは、()(等しいメソッドを実装する必要がある場合のシナリオ(現実世界の例を)知って好奇心)など辞書用のGetHashCode()はいつ行うのですか?

そして、これらを実装するキー必要にカスタムオブジェクトを使用しません機能?

+0

の可能な複製[なぜEqualsメソッドがオーバーライドされたときにGetHashCodeをオーバーライドするのが重要なのですか?](http://stackoverflow.com/questions/371328/why-is-it-important-to-override-gethashcode-when- equals-method-over-over) – nawfal

答えて

13

デフォルトのObject.Equals(参照平等のテスト)で十分でない場合は、EqualsGetHashCodeを上書きする必要があります。これは、たとえば、キーのタイプがカスタムタイプで、カスタムタイプの同じインスタンスでない場合でも、2つのキーが同じであると見なす場合に発生します。例えば

、あなたの鍵は

class Point { 
    public int X { get; set; } 
    public int Y { get; set; } 
} 

のと同じくらい簡単です、あなたが彼らのX sが同じであり、そのY sが同じである、あなたがオーバーライドする必要があります場合は2 Point sの2が等しいと見なされたい場合はEqualsGetHashCode

+0

辞書に関して、EqualsとGetHashCodeは、1)オブジェクトを適切に編集し、 'point.X'を' point.Y'に置き換える必要がありますか?値を削除して辞書に追加する必要がありますか? – LamonteCristo

2

複合キーを作成する必要がある場合(その1つのデータより多くのキーで構成されるキー)です。その複合キーは、これらのメソッドをオーバーライドする必要のあるカスタムタイプになります。

たとえば、アドレスレコードのメモリ内キャッシュがあり、アドレスをキャッシュに格納していないかどうかをチェックして、高価な旅行をデータベースに保存して検索する必要があるとします。住所が通り1の郵便番号フィールドの点でユニークであるとしましょう。彼らは辞書内のキーのための良い候補だろうあなたのAddressCacheKeyタイプがEqualsGetHashCodeメソッドをオーバーライドする

class AddressCacheKey 
{ 
    public String StreetOne { get; set; } 
    public String ZipCode { get; set; } 

    // overrides for Equals and GetHashCode 
} 

static Dictionary<AddressCacheKey,Address> cache; 

ので、あなたが希望:あなたはこのような何かを使用してキャッシュを実装します2つ以上のデータに基づいてレコードを取得するためにデータベースにアクセスする必要があるかどうかを判断することができます。

1

ここには2つの質問があります。

  1. あなたが GetHashCodeメソッドを(実装する必要があります)
  2. あなたは辞書のキーのためのオブジェクトを使用します。

他の人が使用する可能性のあるクラスを作成する場合、参照Equals()が不十分な場合にGetHashCode()とEquals()を定義します。あなたが辞書でそれを使用することを計画しておらず、あなた自身の使い方のためなら、GetHashCode()などをスキップする理由はありません。

2)の場合は、オブジェクトから他の型への一定の時間参照を持つこと。 GetHashCode()は数値を返し、コレクションには参照が格納されるため、Intまたは文字列(オブジェクトが文字列であることを覚えておいてください)に対するオブジェクトの使用には不利益はありません。

9

ちょうどそれを明確にする:Dictionary<TKey, TValue>GetHashCode()についての一つの重要な事があります:辞書決定するためGetHashCodeメソッドを使用して2つのキーが等しい場合、すなわち<TKey>は、カスタム型である場合は、慎重にGetHashCode()を実装する気にする必要があります。 Andrew Hare氏は、カスタムオブジェクトを明白に識別するシンプルなタイプがあれば、これは簡単だと指摘しました。結合された識別子がある場合は、もう少し複雑になります。

例として、複素数をTKeyと見なします。複素数は、実部と虚部によって決定されます。両方とも単純なタイプのものである。 double。しかし、2つの複素数が等しいかどうかをどのように識別しますか?カスタム複合タイプにGetHashode()を実装し、両方の識別パーツを結合します。

さらに詳しくは、hereを参照してください。 Ergwunさんのコメントに基づいて

UPDATE

私はEquals(object)GetHashCode()TKeyの実装に特別に関してDictionary<TKey, TValue>.Addの動作を確認しました。私は は、私は結果にかなり驚いていたことを告白する必要があります。これはキーでdv2にキー​​とv1を追加するときに何が起こるかである二つのオブジェクト​​及びタイプTKeyk2、任意の二つのオブジェクトv1及びタイプTValuev2、及びタイプDictionary<TKey, TValue>の空の辞書dを考える

TKey.Equals(object)TKey.GetHashCode()の実装に応じて)k2秒:

k1.Equals(k2) k1.GetHashCode() == k2.GetHashCode() d.Add(k2, v2) 
false   false         ok 
false   true         ok 
true   false         ok 
true   true         System.ArgumentException 

コンclusion:最初は2番目のケース(Equalsfalseを返しますが、両方のキーオブジェクトが同じハッシュコードを持つと考えていたので間違っていました)はArgumentExceptionになります。しかし、3番目のケースは何らかの方法で辞書が表示されるので、GetHashCode()を使用します。とにかく、同じ型で等しい2つのオブジェクトがインスタンスDictionary<TKey, TValue>が正しく動作するように同じハッシュコードを返さなければならないというのは良いアドバイスと思われます。

+9

-1 Dictionaryは、2つのキーが等しいかどうかを判断するために 'GetHashCode()'を使用しません。つまり、辞書には、キーが同じハッシュコードを持つ別々のエントリを含めることができます。辞書の効率は低いかもしれませんが、それでも機能します。 – Ergwun

+2

+1更新のために: – Ergwun

+0

はい、等しいオブジェクトが同じハッシュコードを返すようにする必要があります(http://msdn.microsoft.com/en-us/library/ms182358.aspxを参照)。 – Ergwun

関連する問題