ハッシュ コードに関する不変型に関する考慮事項はありますか?
コンストラクターで一度生成する必要がありますか?
ハッシュコードが固定されていることをどのように明確にしますか? するべきか?その場合、GetHashCode メソッドではなく、HashCode というプロパティを使用した方がよいでしょうか。それに何か欠点はありますか?(両方を考慮すると機能しますが、プロパティが推奨されます)。
ハッシュ コードに関する不変型に関する考慮事項はありますか?
コンストラクターで一度生成する必要がありますか?
ハッシュコードが固定されていることをどのように明確にしますか? するべきか?その場合、GetHashCode メソッドではなく、HashCode というプロパティを使用した方がよいでしょうか。それに何か欠点はありますか?(両方を考慮すると機能しますが、プロパティが推奨されます)。
ハッシュ コードに関する不変型に関する考慮事項はありますか?
不変型は、正しくハッシュするのが最も簡単な型です。ほとんどのハッシュ コードのバグは、変更可能なデータをハッシュするときに発生します。最も重要なことは、ハッシュと等価性が一致することです。2 つのインスタンスが等しい場合、同じハッシュ コードを持つ必要があります。(逆は必ずしも真ではありません。同じハッシュを持つ 2 つのインスタンスが等しい必要はありません。)
コンストラクターで一度生成する必要がありますか?
これはパフォーマンス最適化手法です。そうすることで、(計算された値を保存するための)スペースの消費量の増加と引き換えに、時間の短縮が可能になります。文書化された目標に対する両方のオプションのパフォーマンスを慎重に測定する、現実的で顧客中心のパフォーマンス テストによって推進されない限り、パフォーマンスの最適化を行うことはありません。慎重に設計された実験により、(1) そうしないと目標を達成できず、(2) そうしないと目標を達成できないことが示された場合は、これを行う必要があります。
ハッシュコードが固定されていることをどのように明確にしますか?
質問がわかりません。ハッシュ コードの変更は例外であり、規則ではありません。ハッシュコードは常に不変であると考えられています。オブジェクトのハッシュ コードが変更された場合、そのオブジェクトはハッシュ テーブルで「失われる」可能性があるため、誰もがハッシュ コードが安定していると想定する必要があります。
GetHashCode メソッドの代わりに、HashCode というプロパティを使用する方が良いですか?
あなたのオブジェクトのどの消費者が「まあ、すべてのオブジェクトにあることが保証されているメソッドである GetHashCode() を呼び出すことができますが、代わりに、まったく同じことを行うこの HashCode ゲッターを呼び出すつもりです」と言うでしょうか? そのような消費者を念頭に置いていますか?
機能の利用者がいない場合は、機能を提供しないでください。
通常、コンストラクターで生成することはありませんが、キャッシュするかどうかを決定する前に、予想される使用法について詳しく知りたいと思います。
大量にハッシュされ、ハッシュの計算に時間がかかる少数のインスタンスが予想されますか? その場合、キャッシングが適切な場合があります。「使い捨て」の可能性のあるインスタンスが多数予想される場合は、わざわざキャッシュする必要はありません。
興味深いことに、.NET と Java は、この点で String に対して異なる選択をしました。Java はハッシュをキャッシュしますが、.NET はキャッシュしません。多くの文字列インスタンスは決してハッシュされず、ハッシュされたインスタンスはしばしば 1 回だけハッシュされるため (たとえば、ハッシュ テーブルへの挿入時)、私はここで .NET の決定を支持すると思います。
基本的に、メモリと複雑さを速度と交換しています。Michael が言うように、コードをより複雑にする前にテストしてください。もちろん、場合によっては (クラス ライブラリなど)、実際の使用状況を正確に予測できないこともありますが、多くの場合、かなり良いアイデアが得られます。
ただし、別のプロパティは必要ありません。誰かがオブジェクトの状態を変更しない限り、ハッシュ コードは常に同じままである必要があります。型が不変の場合は、既にそれを禁止しているため、ユーザーは変更を期待するべきではありません。オーバーライドするだけGetHashCode()
です。
が初めて呼び出されたときにハッシュ コードを 1 回生成しgetHashCode
、その後の呼び出しのためにそれをキャッシュします。これにより、必要でない可能性があるときにコンストラクターで呼び出すことを回避できます。
getHashCode
値オブジェクトごとに何度も呼び出すことを想定していない場合は、値をキャッシュする必要がまったくない場合があります。
GetHashCode() メソッドをオーバーライドする必要があります。これは、消費者がハッシュコードを取得する方法です。ほとんどのハッシュコードはかなり単純な算術演算であり、すぐに実行されます。結果をキャッシュすると (メモリ コストがかかります)、顕著なパフォーマンスの向上が得られると信じる理由はありますか?
簡単に始めましょう - その場でハッシュコードを生成します。キャッシュすることでパフォーマンスが向上すると思われる場合は、まずテストしてください。
規制により、この時点で「時期尚早の最適化はすべての悪の根源である」という引用を参照する必要があります。
私の個人的な経験から、開発者はパフォーマンスの問題を誤って判断するのが非常に得意であることを知っています。
そのため、GetHashCode() でその場でハッシュ コードを計算する際は、すべてをできるだけシンプルに保つことをお勧めします。
一般に、HashCode の計算は高速である必要があります。そのため、キャッシングは最適化の対象ではなく、問題に値するものではありません。
プロファイリングで GethashCode にかなりの時間がかかることが実際に示されている場合は、修正としてそれをキャッシュする必要があります。
しかし、私はそれを通常の練習の一部とは考えていません。
ハッシュコードが固定されていることを確認する必要があるのはなぜですか? ハッシュコードのセマンティクスは、オブジェクトの特定の状態に対して常に同じ値になるということです。オブジェクトは不変であるため、これは当然のことです。GetHashCode をどのように実装するかは、あなた次第です。
返されるプライベート フィールドを使用することも 1 つの選択肢です。これは、小さく、簡単で、高速です。