2009-03-04 14 views
4

私がEqualsをオーバーライドする場合は、GetHashCodeをオーバーライドする必要があります(逆も同様です)。新しいクラスでGetHashCodeとEqualsをオーバーライドする必要がありますか?

しかし、私は疑問に思っています。私は常にこれらの2つをどのクラスでもオーバーライドする必要がありますか?特に私が辞書や類似のコレクションでそれらを使用することを知っていたら?これはfairly straight forwardですが、それはまだすべてのクラスのための余分な仕事です。

System.Objectの実装がこれを心配するほど悪いですか?

編集:値と参照の等価性はもう少し詳しく説明できますか?だから私は両方の "テスト"である2つの文字列(s1とs2)を持っている場合、それらは等しい値ですが、2つの異なる文字列なので、それらは参照イコールではありませんか? [OK]を、文字列のために考えるのは簡単ですが、参照や値の平等が必要な一般的な状況は何ですか?

答えて

6

私が知っている限り、値の同等性のセマンティクスが必要な場合は、オーバーライドする必要があります。 System.Objectの実装は「悪い」ではなく、参照チェック(そのレベルで実行できるすべての実装)だけです。

要するに、値に基づく等価性(クラスのプロパティに基づく等価性)が必要な場合は、yesを上書きします。それ以外の場合は、既にそれ以上のものでなければなりません。

EDIT: あなただけは、上記のケースでそれらを上書きするを必要としています。あなたが1つをオーバーライドする場合は、明白な理由のために両方をオーバーライドする必要があります(一貫性が必要など)。 は、他の回答(ハッシュ値を使用するアルゴリズムのパフォーマンス、つまりDictionaryキーなど)に記載されているその他の理由ですべてのクラスでそれらをオーバーライドできますが、デフォルトのSystem.Objectの実装は正しく動作します。

EDIT 2: 詳細情報が必要です。現状では

public class User { 
    private int _id; 
    private string _username; 
    public string Username { get {return _username;}}; 
    // [snip] Whatever other properties we might like to have. 

    public User(string username) { 
     // Initialise our user from a database, or whatever. 
    } 
} 

、次のコードを、直感的に思えるかもしれません:以下の疑似クラスを考えてみましょう

User foo = new User("me"); 
User bar = new User("me"); 
User baz = foo; 

if (foo.Equals(bar)) { 
    Console.WriteLine("1: Success!"); 
} 
if (foo.Equals(baz)) { 
    Console.WriteLine("2: Success!"); 
} 

しかし、それだけでプリントアウトします:

2:成功を

なぜですか? foobarは、クラスの2つの別々のインスタンスであり、別々の参照を持っています。参照はC/C++のポインタに似ています。 fooとbazは、一方が他方から割り当てられているため、同じ参照です。彼らはすべて同じの値を持っていますが、ユーザーは「私」と呼ばれています。 .Equals実装をベース値のサンプル実装は次のようになります。

partial class User { 
    public override bool Equals(object b) { 
     if (b == null) return false; 
     if (b.GetType() != this.GetType()) return false; 

     // Now the heavy lifting 
     User other = (User)b; 
     if (other._id == this._id) return true; 
     else return false; 
    } 
} 

は、それが平等を決定するために、クラスのプロパティの一部に対してチェックする方法を参照してください?それは仕事での価値の平等です。参照の平等は単純なthis == bのチェックに過ぎません。

2

Valueセマンティクスが必要な場合のみ。MSDNから:

オブジェクトのいくつかの種類のために、それが持っていることが望ましい が 価値の平等の代わりに、参照 平等のためのテストを等しいです。 のような実装は、彼らが同じインスタンス ない場合であっても、同じ値を持つ 二つのオブジェクト場合はtrueを返し等しいです。オブジェクトの値 を構成するものの定義 は、タイプが の実装者次第ですが、通常、オブジェクトのインスタンス変数 に格納されているデータの一部またはすべてです。たとえば、文字列の値 は、文字列の文字 に基づいています。 のEqualsメソッドは、Stringクラスは 同じ順序で まったく同じ文字を含む文字列のいずれか 2つのインスタンスのためにtrueを返します。

3

は一貫してである必要があります。換言すれば、2つのオブジェクトが等しいである場合、それぞれが同じハッシュコードを返すべきです。これは、ハッシュコレクションで特に重要です。ハッシュされたコンテナ内のオブジェクトXに一致するオブジェクトを検索するには、コンテナはXと同じハッシュコード

+0

優秀なポイントを持って平等のためにそれらの項目をテストします。 – Alan

関連する問題