Search code examples
.netvb.netequalitygethashcode

Overriding GetHashCode variations


I have a theoretical class Name_Order, that has a string Name and a int Order.

I need to indicate that two Name_Order's are different, if the pair NameOrder is different, that is, or name or order are different.

Now, overriding Equals no problemo, but I have some "issues" with GetHashCode:

Public Class Name_Order
  Public Property Name As String
  Public Property Order As Integer

  Public Overrides Function Equals(ByVal obj As Object) As Boolean
    If TypeOf obj Is Name_Order Then
      Dim no = DirectCast(obj, Name_Order)
      Return Me.Name = no.Name AndAlso Me.Order = no.Order
    Else
      Return MyBase.Equals(obj)
    End If
  End Function

  Public Overrides Function GetHashCode() As Integer
    Dim hcName = 0
    If Me.Name IsNot Nothing Then
      hcName = Me.Name.GetHashCode
    End If

    Dim hcOrder = Me.Order.GetHashCode

    Return hcName + hcOrder
  End Function
End Class

In that case, summing the hashcodes, leave a (small, but real) possibility that two distinct Name_Orders with different names or orders be "identical".

Say, adding the 7 + 154 gives the same result as adding 154 + 7...

An alternative override of that method?


Solution

  • Firstly, while avoiding collisions is good, it isn't a problem if there are collisions. But a common approach is something like:

    return 7 * x.GetHashCode() + y.GetHashCode();
    

    This is more noticeable in, for example, a point/position, where it would be nice to avoid obvious diagonal collisions like (2,3) vs (3,2).

    A much bigger problem in your code is that the properties in the hash/equals are mutable; if they get changed, any usage in dictionaries etc will stop working. You should prefer read-only key values.