Home » excel » excel – Overload Equals / GetHashCode in VB.NET to Use Objects as Dictionary Keys

excel – Overload Equals / GetHashCode in VB.NET to Use Objects as Dictionary Keys

Posted by: admin May 14, 2020 Leave a comment

Questions:

I have a Dictionary whose keys are Excel Range objects (no, this is not negotiable), defined as follows (the type CellProp is an object that contains various cell properties):

Dim dic As New Dictionary(Of Excel.Range, CellProp)(New RangeComparer())

Because the keys are objects, I need to overload the Equals/GetHashCode functions. My current implementation is as follows:

Class RangeComparer
Implements IEqualityComparer(Of Excel.Range)
Public Overloads Function Equals(ByVal x As Excel.Range, ByVal y As Excel.Range) As Boolean Implements IEqualityComparer(Of Excel.Range).Equals
    If x.Address(External:=True) = y.Address(External:=True) Then
        Return True
    Else
        Return False
    End If
End Function
Public Overloads Function GetHashCode(ByVal obj As Excel.Range) As Integer Implements IEqualityComparer(Of Excel.Range).GetHashCode
      Return obj.Count.GetHashCode
    End Function
End Class

However, this can be pretty slow to execute when adding many cells (i.e. hundreds) to the Dictionary at once. Most importantly, is there a faster way to do this? Secondarily, why does getting the hash code for the Range’s Count property seem to work (albeit slowly)?

How to&Answers:

You may want to do a little research into how hash codes work. Hash codes are 100% arbitrary and definable by the programmer. The only thing that matters is that if two instances are not the same, then their hash codes should be different. If you have a collection where almost all hash codes are identical (i.e., count = 1), then your dictionary still works just fine, but it degrades into a linear search, which is very inefficient. This is because almost all of the instances are generating hash collisions, so there is no benefit provided by the hashing into buckets.

For instance, another hash code algorithm you could try is generating one from the names of the cells, which should have a lot fewer hash collisions:

Public Overloads Function GetHashCode(ByVal obj As Excel.Range) _
    As Integer Implements IEqualityComparer(Of Excel.Range).GetHashCode

  Return obj.Address(External:=True).GetHashCode

End Function