いつ、どのようにオーバーライドするかについて、約 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
この種の参照型は、主キーでそれらを識別するためにリレーショナル データベースに格納されていない限り、ほとんどの参照型は通常、不変フィールドを持たないことがわかっているため、参照型のオーバーライドの有用性を損なうようです。