いつ、どのようにオーバーライドするかについて、約 10 の異なる質問を読みましたが、GetHashCodeまだよくわからないことがあります。のほとんどの実装はGetHashCode、オブジェクトのフィールドのハッシュ コードに基づいていますが、 の値はGetHashCodeオブジェクトの存続期間にわたって変更されるべきではないとされています。それが基づいているフィールドが可変である場合、それはどのように機能しますか? また、オーバーライドされたものではなく、参照の等価性に基づいて辞書検索などを行いたい場合はどうすればよいEqualsですか?
私は主にEquals、シリアル化と逆シリアル化 (私の場合は XML へ) によって参照の等価性が失われると想定しているシリアル化コードの単体テストを容易にするためにオーバーライドしているため、少なくとも値の等価性によって正しいことを確認したいと考えています。この場合、オーバーライドEqualsするのは悪い習慣ですか? 基本的に、実行中のコードのほとんどで、参照の等価性が必要であり、常に使用==しており、それをオーバーライドしていません。ValueEqualsオーバーライドする代わりに、新しいメソッドなどを作成する必要がありますEqualsか? 私は、フレームワークが常に物事を比較するために and を使用==しないと想定していたEqualsので、オーバーライドしても安全だと思っていEqualsました。==オペレーター。他のいくつかの質問を読むと、そうではないようです。
編集:
私の意図が不明確だったようです。私が言いたいのは、99% の時間は単純な古い参照の等価性、デフォルトの動作、驚きがないことを望んでいるということです。.Equals非常にまれなケースですが、値の等価性が必要であり、代わりに を使用して値の等価性を明示的に要求したいと考えています==。
これを行うと、コンパイラはオーバーライドGetHashCodeも推奨するため、この質問が出てきました。GetHashCode変更可能なオブジェクトに適用する場合、次のような矛盾する目標があるように見えました。
- もしそう
a.Equals(b)なら。a.GetHashCode()== b.GetHashCode() - の値は
a.GetHashCode()、 の存続期間中は変更されませんa。
オブジェクトの状態が変化すると、 の値が変化することが予想されるため、これらは当然矛盾しているように.Equals()見えGetHashCodeます。.Equals()GetHashCode
なぜこのような矛盾があるように見えるのでしょうか? これらの推奨事項は、変更可能なオブジェクトに適用するためのものではありませんか? おそらく想定されていますが、構造体ではなくクラスについて言及していることに言及する価値があるかもしれません。
解像度:
私は JaredPar を承認済みとしてマークしていますが、主にコメントのやり取りのためです。ここから学んだことをまとめると、すべての目標を達成し、エッジ ケースで発生する可能性のある風変わりな動作を回避する唯一の方法は、オーバーライドEqualsしGetHashCodeて不変フィールドに基づくか、または を実装することIEquatableです。Equalsこの種の参照型は、主キーでそれらを識別するためにリレーショナル データベースに格納されていない限り、ほとんどの参照型は通常、不変フィールドを持たないことがわかっているため、参照型のオーバーライドの有用性を損なうようです。