2

そのようなクラスがあるとしましょう:

class MyClass
{
    public string SomeValue { get; set; }

    // ...
}

ここで、プロパティがMyClass等しい場合、2 つのインスタンスが等しいとしましょう。したがって、それを表すメソッドとSomeValueを上書きします。を返しますが、同時に次のルールに従う必要があります。Object.Equals()Object.GetHashCode()Object.GetHashCode()SomeValue.GetHashCode()

  1. オブジェクトの 2 つのインスタンスが等しい場合、それらは同じハッシュ コードを返す必要があります。
  2. ハッシュ コードは、ランタイム全体で変更しないでください。

しかし、どうやらSomeValue変更される可能性があり、以前に取得したハッシュ コードが無効になる可能性があります。

クラスを不変にすることしか考えられませんが、この場合他の人が何をしているのか知りたいです。

そのような場合はどうしますか?そのようなクラスを持つことは、設計上の決定における微妙な問題を表していますか?

4

3 に答える 3

2

変更可能な値に依存している場合GetHashCode()は、値が変更されるたびにハッシュを変更する必要があります。そうしないと、平等法に違反します。

オブジェクトをHashSetまたは 内のキーとしてDictionary. このような場合、そのようなコンテナーに格納されている限り、ハッシュ コードが変更されないようにする必要があります。これは、プログラム時にこの問題に対処するだけで手動で確保することもFreeze()、オブジェクトに何らかのメソッドを提供することもできます。これが呼び出された場合、その後プロパティを設定しようとすると、何らかの例外が発生します (また、何らかのDefrost()メソッドを提供する必要があります)。Freeze()さらに、メソッドの呼び出しをGetHashCode()実装に入れるため、凍結されたオブジェクトを誤って変更する人がいないことを確信できます。

最後に 1 つだけヒントがあります。そのようなコンテナー内のオブジェクトを変更する必要がある場合は、単純に削除して変更し (解凍することを忘れないでください)、再度追加します。

于 2012-12-07T16:04:16.017 に答える
2

一般的な契約では、 A.equals(B) が true の場合、それらのハッシュ コードは同じである必要があります。A.equals(B) が true ではなくなるような方法で A の SomeValue が変更された場合、A.GetHashCode() は以前とは異なる値を返す可能性があります。可変オブジェクトは GetHashCode() をキャッシュできません。メソッドが呼び出されるたびに計算する必要があります。

この記事には、GetHashCode と可変性に関する詳細なガイドラインがあります。

http://ericlippert.com/2011/02/28/guidelines-and-rules-for-gethashcode/

于 2012-12-07T01:10:27.107 に答える
1

可変性と「等しい」オブジェクトに対して同じ値を返す GetHashCode のどちらかを選択する必要があります。多くの場合、変更可能なオブジェクトに 'equal' を実装する必要があると考えると、後で "shades of equals" があり、実際には Object.Equals が等しいという意味ではないと判断することになります。

あらゆる種類のデータ構造の「キー」として可変オブジェクトを持つことは、私にとって大きな危険信号です。例えば:

MyObj a = new MyObj("alpha");
MyObj b = new MyObj("beta");
HashSet<MyObj> objs = new HashSet<MyObj>();
objs.Add(a);
objs.Add(b);
// objs.Count == 2
b.SomeValue = "alpha";
// objs.Distinct().Count() == 1, objs.Count == 2

の契約にひどく違反しましたHashSet<T>。これは明らかな例であり、微妙なものがあります。

于 2012-12-07T01:33:03.687 に答える