Search code examples
vb.netiequatable

Have implemented IEquatable correctly? Should I always override GetHashCode?


I saw the question posed here: Have I implemented Equals()/GetHashCode() correctly? but my c# is not as strong, and I am unfimiliar with IEquatable enough that I would like to see this in VB.NET if possible please.

My example code (The class will eventually use INotifyPropertyChanged when I get there):

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

Thanks,


Solution

  • You really do need to implement Overrides for the object.Equals and object.GetHashCode implementations.

    Basically, implementing IEquatable(of T).Equals by itself will only work so long as the caller KNOWS to call IEquatable(of T).Equals instead of regular object.Equals.

    Consider if you have an ArrayList of Cars and check if the list Contains(myCar), where myCar's Make and Model are the same as a car in the ArrayList...but the one in the ArrayList isn't actually the exact same instance. Contains would return false.

    Worse yet, if you had a Hashtable or Dictionary, which uses GetHashCode to determine where to store entries, equality would never work because two cars with the same Make and Model would return different values for GetHashCode()

    Basically, it comes down to you adding the following implementations to car:

    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
    

    So the question I have is: why implement IEquatable at all? Why not just override Equals and GetHashCode?