2011-09-05 16 views
10

こんにちは私は6文字列のプロパティを持つクラスを持っています。一意のオブジェクトは、これらのフィールドの少なくとも1つに異なる値を持ちます。C#.NET GetHashCode関数の質問

IEqualityComparerのGetHashCode関数を実装するには、6つのプロパティをすべて連結し、結果の文字列でGetHashCodeを呼び出します。

私は、次の疑問だった:

  1. が一意の値にGetHashCodeメソッドを呼び出すことが必要ですか?
  2. 6つのプロパティの連結操作で比較が遅くなりますか?
  3. 他の方法を使用する必要がありますか?あなたはそれらのオブジェクトに等号()を呼び出す場合
+0

です配列などでソートするなど、オブジェクトをどこかで比較する計画ですか?それは、あなたは、私はList.Containsメソッドのためにそれを使用して、それを比較するオブジェクトを渡して、私はそれを変更するか、あなたはGetHashCode – mydogisbox

+0

こんにちはmydogisboxを実装する必要があります変更されます。私はすでにEqualsを実装しており、GetHashcodeの正しいアプローチを知らないのです。 – ganeshran

答えて

3

GetHashCode "不等な"オブジェクトに等しくない値を返す必要はありません。等しいオブジェクトに対して等しい値を返すだけで済みます(オブジェクトの存続期間中も同じ値を返す必要があります)。

これが意味:2つのオブジェクトがEqualsと等しいとした場合、その後、そのGetHashCodeが同じ値を返す必要があります

  1. 6つの文字列プロパティの一部が厳密には読み取り専用でない場合、それらはGetHashCode実装に参加できません。

同時に両​​方の点を満たすことができない場合は、他に何かがバグのためにドアを開いたままにするので、デザインを再評価する必要があります。

最後に、GetHashCodeを6つの文字列のそれぞれにGetHashCodeを呼び出し、6つの結果すべてを1つの値にビット単位の操作を使用して統合することで、より高速にすることができます。

+0

こんにちは、私の物件はどれも読み取り専用ではありません。しかし、それらはすべてプライベートセッターを持っていますが、コンストラクターからのみ変更できます。これはGetHashCodeでの使用に影響しますか? – ganeshran

+0

@ganeshran:それは、オブジェクトの存続期間にわたって効果的に読み込み専用です(つまり、必要であれば 'readonly'バッキングフィールドで実装できます)。これで十分です。あなたは大丈夫です。 – Jon

+0

@Jon 'GetHashCode()'実装のための条件を読んでいると、それは競合する要件に問題があることがわかります。実際、あなたは部分的に正しいだけです。 'GetHashCode()'メソッドの実際の必要条件は次のとおりです。 1.等しいオブジェクトに対して同じ値を返さなければなりません。 2.変更されていない同じオブジェクトに対して同じ値を返す必要があります。 3. GetHashCode()は高速である必要があります。 それにはいくつか推奨事項があります。たとえば、これは:最高のパフォーマンスのために、ハッシュ関数はすべての入力に対してランダムな分布を生成する必要があります。 –

3

GetHashCodeメソッド()がtrueを返すすべてのオブジェクトに対して同じハッシュコードを返す必要があります。これは、たとえば、フィールド値が何であるかにかかわらず、ハッシュコードとしてゼロを返すことができることを意味します。しかし、これは、ハッシュテーブルなどのデータ構造に格納すると、オブジェクトを非常に非効率にします。

文字列を組み合わせることもできますが、たとえば、equalsのすべての文字列を比較しながら、ハッシュコードの2つの文字列を組み合わせることもできます。

結合された文字列の単一のハッシュを計算するのではなく、6つの別々の文字列のハッシュを組み合わせることもできます。私は、これは文字列を連結するよりもかなり高速になりますかどうかわからないんだけど例 Quick and Simple Hash Code Combinations

を参照してください。

+0

Anders氏に感謝します。Containsメソッドの比較にのみ使用しています。ハッシュコードに2つの文字列しか結合しない場合、オブジェクトの2つの値が同じであれば、ハッシュコードは同じではありませんか?これは比較を混乱させるか、GetHashCodeは比較自体に影響を及ぼさず、パフォーマンスにのみ影響します – ganeshran

+1

他の人は既にこの点を作っていますが、あなたの直感は違う方法で対処したいと思います立ち往生した。 GetHashCode()が2^32の異なる値しか取れないintを返すことを確認してください。あなたのオブジェクトは、任意の長さの6つの文字列で構成されており、はるかに多くの値を取ることは明らかです。この例では、GetHashCode()がオブジェクトのすべての可能な値に対して一意の値になることは容易にはわかりません。このプロパティを満たす必要があります: "a.Equals(b)a.GetHashCode()== b.GetHashCode()"; "if"が両方向に通らないことに注意してください。 –

+1

GetHashCode()の実際の考慮事項は、それが「良い」と「高速」であることです。 "高速"にするために、私はすべてのメモリ割り当てと文字列のコピーを避けようとします。それを「良い」ものにすることはいくらかのニュアンスの対象ですが、実際には、@Jonが示唆するように、サブオブジェクトのGetHashCode()値を一緒に振ることで十分です。 ReSharperの提案を「回答」として投稿し、コードの書式設定を行うことができます。 –

4

あなたの文字列フィールドは、AFの名前とヌルではないことが知られている場合、これはあなたのGetHashCodeメソッド(のためのReSharperの提案である)

public override int GetHashCode() { 
    unchecked { 
    int result=a.GetHashCode(); 
    result=(result*397)^b.GetHashCode(); 
    result=(result*397)^c.GetHashCode(); 
    result=(result*397)^d.GetHashCode(); 
    result=(result*397)^e.GetHashCode(); 
    result=(result*397)^f.GetHashCode(); 
    return result; 
    } 
} 
+0

ありがとう、私はこのコードを使用します。 – ganeshran

+0

私の答えを見てください:http://stackoverflow.com/a/34006336/1911540 –