インターネット上には何百もの同様の質問が投稿されているため、あなたがすべて怒ってしまう前に、私は最後の数時間を費やしてそれらすべてを読んだだけで、私の質問に対する答えが見つからなかったことを保証できます.
バックグラウンド:
基本的に、私の大規模なアプリケーションの 1 つは、現在選択されている項目を編集した後Binding
に、プロパティの一部の が機能しなくなっListBox.SelectedItem
たり、プログラムがクラッシュしたりする状況に悩まされていました。最初に、「同じキーを持つアイテムが既に追加されています」コードの質問から ListBoxItem を選択する際の例外をここで尋ねましたが、回答がありませんでした。
その問題を解決するために数日与えられた今週まで、私はその問題に取り組む時間がありませんでした。簡単に言うと、問題の原因がわかりました。これは、データ型クラスがEquals
メソッドをオーバーライドしたため、GetHashCode
メソッドもオーバーライドされたためです。
この問題に気付いていない人のために、不変のフィールド/プロパティGetHashCode
を使用してのみメソッドを実装できることを発見しました。Overriding GetHashCode()投稿に対する Harvey Kwok の回答からの抜粋を使用して、これを説明します。
問題は、GetHashCode が Dictionary および HashSet コレクションによって使用され、各項目をバケットに配置することです。いくつかの変更可能なフィールドに基づいてハッシュコードが計算され、オブジェクトが HashSet または Dictionary に配置された後にフィールドが実際に変更された場合、そのオブジェクトは HashSet または Dictionary から見つけることができなくなります。
メソッドで変更可能なプロパティを使用したため、実際の問題が発生しました。ユーザーが UI でこれらのプロパティ値を変更すると、オブジェクトに関連付けられたハッシュ コード値が変更され、アイテムがコレクション内で見つからなくなりました。GetHashCode
質問:
それで、私の質問は、GetHashCode
不変フィールドのないクラスにメソッドを実装する必要がある状況を処理する最良の方法は何ですか? 申し訳ありませんが、その質問は以前に尋ねられたので、より具体的にさせてください。
Overriding GetHashCode()投稿の回答は、これらの状況では、単に定数値を返す方がよいことを示唆しています...値を返すことを提案する人もいれば1
、素数を返すことを提案する人もいます。個人的には、これらの提案に違いは見られません。なぜなら、どちらにも使用されるバケットは 1 つしかないと思っていたからです。
さらに、 Eric Lippert のブログにあるGetHashCode のガイドラインとルールの記事には、「ガイドライン: ハッシュ コードの配布は「ランダム」でなければならない」というセクションがあり、十分なバケットが使用されない結果となるアルゴリズムを使用する場合の落とし穴が強調されています。彼は、使用するバケットの数を減らし、バケットが非常に大きくなるとパフォーマンスの問題を引き起こすアルゴリズムについて警告しています。確かに、定数を返すことはこのカテゴリに分類されます。
Guid
すべてのデータ型クラス (データベースではなく C# のみ) に特別なフィールドを追加して、特にGetHashCode
メソッド内でのみ使用するというアイデアがありました。この長い紹介の最後に、私の実際の質問は、どちらの実装が優れているかということだと思います。要約すると:
概要:
不変フィールドのないクラスで Object.GetHashCode() をオーバーライドする場合、メソッドから定数を返すか、メソッドでのみ使用するためにクラスごとGetHashCode
に追加のフィールドを作成する方が良いですか? 新しいフィールドを追加する必要がある場合、どのタイプにする必要がありますか?メソッドに含める必要はありませんか?readonly
GetHashCode
Equals
誰からの回答も喜んで受け取りますが、このテーマについて十分な知識を持つ上級開発者から回答を受け取ることを本当に望んでいます。