是否正确实现了IEquatable?我应该总是覆盖GetHashCode吗?

时间:2012-03-18 06:38:08

标签: vb.net iequatable

我看到了这里提出的问题:Have I implemented Equals()/GetHashCode() correctly?但是我的c#并不那么强大,而且我对IEquatable不够熟悉,如果可能的话,我希望在VB.NET中看到这个。

我的示例代码(当我到达那里时,该类最终将使用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

谢谢,

2 个答案:

答案 0 :(得分:3)

您确实需要为object.Equals和object.GetHashCode实现实现Overrides。

基本上,实现IEquatable(of T).Equals本身只会在调用者知道调用IEquatable(T).Equals而不是常规object.Equals时起作用。

考虑你是否有一个CarsList的ArrayList并检查列表是否包含(myCar),其中myCar的Make和Model与ArrayList中的汽车相同......但是ArrayList中的那个实际上并不是确切的相同的实例。包含将返回false。

更糟糕的是,如果您有一个Hashtable或Dictionary,它使用GetHashCode来确定存储条目的位置,那么相等性将永远不会起作用,因为具有相同Make和Model的两辆汽车将为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?

答案 1 :(得分:1)

仅对结构或密封类实现IEquatable<T>IEquatable<T>.Equals(T)的任何合法实现都需要具有与类的Object.GetHashCode()重写兼容的语义,而{1}}必须具有与类的Equals(Object)重写兼容的语义。如果一个类型没有被密封,那么确保派生类型的IEquatable<T>.Equals(T)实现与它们覆盖Object.Equals(Object)兼容的唯一方法就是将前一个方法链连接到后者,实际上使任何一个方法无效人们可能首先从实施IEquatable<T>获得了优势。

实现IEquatable<T>通常是结构类型的一大胜利(在每次比较中保存装箱操作),而对于其他密封类型则稍微小一些(在每次比较时都节省了一个类型)。除非性能至关重要,否则我可能会跳过大多数非结构类型,即使它们是密封的。