2012-03-18 9 views
2

私はここでポーズされた質問を見た:Have I implemented Equals()/GetHashCode() correctly?しかし、私のC#は強力ではなく、私はIEquatableに慣れていないので、私は可能な限りVB.NETでこれを見たいと思っています。IEquatableを正しく実装しましたか?私は常にGetHashCodeをオーバーライドする必要がありますか?

私のサンプルコード(私はそこに着くときに、クラスは、最終的にINotifyPropertyChangedのを使用します):

Public Class Car 
Implements ICloneable 
Implements IEquatable(Of Car) 

Public Property Make() As String 
    Get 
     Return m_Make 
    End Get 
    Set(ByVal value As String) 
     m_Make = value 
    End Set 
End Property 
Private m_Make As String 

Public Property Model() As String 
    Get 
     Return m_Model 
    End Get 
    Set(ByVal value As String) 
     m_Model = value 
    End Set 
End Property 
Private m_Model As String 

Public Function Clone() As Object Implements System.ICloneable.Clone 
    Return New Car() With { _ 
    .Make = Me.Make, _ 
    .Model = Me.Model _ 
    } 
End Function 

Public Overloads Function Equals(ByVal other As Car) As Boolean Implements System.IEquatable(Of Car).Equals 
    Return other.Make = Me.Make AndAlso other.Model = Me.Model 
End Function 
End Class 

おかげで、

答えて

3

あなたは本当にはObject.equalsとObject.GetHashCodeを実装するためにオーバーライドを実装する必要があります。

IEquatable(of T).Equalsを単独で実装することは、呼び出し側がKNOWSのIEquatable(Tの).Equalsを通常のobject.Equalsの代わりに呼び出す限り動作します。

もしあなたがCarsのArrayListを持っていて、リストContains(myCar)がmyCarのMakeとModelがArrayListの車と同じであるかどうかを確認すると、ArrayList内のcarは実際には全く同じインスタンス。 Containsはfalseを返します。まだ

さらに悪いことに、あなたは同じ製造元とモデルとの2台の車がGetHashCodeメソッドに異なる値を返しますので、平等が

)(働くことはない、エントリを格納する場所を決定するGetHashCodeメソッドを使用してハッシュテーブルや辞書を、持っていた場合基本的に、それは車に、次の実装を追加し、あなたにダウンしています:

Public Overrides Overloads Function Equals(obj As Object) As Boolean 
    Return TypeOf obj Is Car AndAlso Equals(DirectCast(obj, Car)) 
End Function 

Public Overrides Function GetHashCode() As Int32 
    Dim hash As Int32 = 179 ' or something intelligent 

    hash = hash * 27 + Make.GetHashCode() 
    hash = hash * 27 + Model.GetHashCode() 

    Return hash 
End Function 

だから私は持っている質問です:なぜすべてでIEquatableを実装しますか?なぜEqualsとGetHashCodeをオーバーライドしないのですか?

+0

私はリポジトリパターンを実装できるようにIEquatableを実装しています。ハッシュコードは、同じプロパティを持つ2つのオブジェクトの問題をどのように解決しますか?また、なぜ "何かインテリジェントな"コメント?申し訳ありませんが、私は少し高密度から出てくる。 ChangeTrackerからEqualsが使用されています:https://gist.github.com/2065076 –

+0

ハッシュコードを実装する方法はいろいろあります。 179と27は私が選んだ数字です。重要な部分は、ハッシュコードがあなたのEqualsオーバーライドのようにMakeとModelに基づいていることに気づくことです。 – Jeff

+0

私はあなたのChangeTrackerを参照してください...しかし、私はあなたがすでにObject.Equalsをオーバーライドする必要があるということを言おうとしているので、IEquatableも実装する必要はありません。 – Jeff

1

構造体または密封クラスに対してはIEquatable<T>を実装するだけです。 IEquatable<T>.Equals(T)の正当な実装では、クラスのオーバーライドObject.GetHashCode()と互換性があるセマンティクスが必要です。クラスのオーバーライドEquals(Object)と互換性があります。型が封印されていない場合、派生型の実装がIEquatable<T>.Equals(T)であることを確実にするための唯一の方法は、Object.Equals(Object)のオーバーライドと互換性があり、後者への前のメソッド連鎖を持ち、IEquatable<T>最初は

IEquatable<T>を実装すると、多くの場合、構造体型(すべての比較時にボクシング操作を保存する)と他の密封型の勝利が若干小さくなります(比較ごとに型キャストが保存されます)。パフォーマンスが重要でない限り、シールされていてもほとんどの非構造体型はスキップしてしまうでしょう。

+0

この意味は逆のことではありませんか?私。 .Equalsをオーバーライドする場合、私はIEquatableまたはIEqualityComparerを実装するために慣習で要求されていませんか? –

+0

@OmarMir: 'IEquatable .Equals(T)'が 'Object.Equals(Object)'にマッチするという要件は、 'IEquatable 'を実装しているか、そうでない型から派生する型にのみ適用されます。 'IEquatable 'を実装していない型は、この要件から免除されます。 – supercat

関連する問題