8

少なくとも 1 つのフィールドが一致するGetHashCode場合にオブジェクトが等しいと見なされる場合、関数をオーバーライドする最良の方法は何でしょうか。

ジェネリックEqualsメソッドの場合、例は次のようになります。

    public bool Equals(Whatever other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;

        // Considering that the values can't be 'null' here.
        return other.Id.Equals(Id) || Equals(other.Money, Money) ||
               Equals(other.Code, Code);
    }

GetHashCodeそれでも、この場合の適切な実装を行うことについて混乱しています。

これはどのように行うべきですか?

ありがとうございました。

4

3 に答える 3

17

Equalsこれは推移的ではないため、 のひどい定義です。

検討

x = { Id = 1, Money = 0.1, Code = "X" }
y = { Id = 1, Money = 0.2, Code = "Y" }
z = { Id = 3, Money = 0.2, Code = "Z" }

そしてx == yy == zしかしx != z

さらに、 の唯一の合理的な実装GetHashCodeは定数マップであることを立証できます。

とが別個のオブジェクトであるxとします。オブジェクトにしyましょうz

z = { Id = x.Id, Money = y.Money, Code = "Z" }

そしてx == zy == zそれx.GetHashCode() == z.GetHashCode()y.GetHashCode() == z.GetHashCode()確立しx.GetHashCode() == y.GetHashCode()ます。xyは恣意的だったので、 がGetHashCode一定であることを確立しました。

したがって、可能な実装は次のとおりであることを示しましたGetHashCode

private readonly int constant = 17;
public override int GetHashCode() {
    return constant;
}

これらすべてをまとめると、モデル化しようとしている概念を再考し、 の別の定義を考え出す必要があることが明らかになりますEquals

于 2011-04-05T16:01:20.840 に答える
7

これにEqualsを使用するべきではないと思います。イコールが何を意味するかについて人々は非常に明確な概念を持っており、ID が異なっていてもコードまたは名前が同じである場合、私はそれらを「イコール」とは見なしません。「IsCompatible」のような別のメソッドが必要になるかもしれません。

それらをグループ化できるようにしたい場合は、これらのオブジェクトのリストで拡張メソッド ToLookup() を使用して、IsCompatible メソッドになる述語を使用できます。その後、それらはグループ化されます。

于 2011-04-05T15:57:08.120 に答える
6

黄金律は次のとおりです。オブジェクトが同等に比較される場合、それらは同じハッシュコードを生成する必要があります。

したがって、適合した(ただし、望ましくない)実装は次のようになります。

public override int GetHashCode()
{
    return 0;
}

率直に言って、もしIdNameそしてCode互いに独立しているなら、あなたがもっとうまくやれるかどうかはわかりません。このタイプのオブジェクトをハッシュテーブルに入れるのは面倒です。

于 2011-04-05T15:58:55.157 に答える