Переопределение вариантов GetHashCode - PullRequest
1 голос
/ 06 октября 2011

У меня есть теоретический класс Name_Order, в котором есть строка Name и int Order.

Мне нужно указать, что два Name_Order различны, если пара NameOrder отличаетсято есть или имя или порядок отличаются.

Теперь переопределение равно 10000 * без проблем , но у меня есть некоторые "проблемы" с 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

Вв этом случае, суммируя хеш-коды, оставляют (небольшую, но реальную) вероятность того, что два разных Name_Order с разными именами или порядками будут «идентичны».

Скажем, добавление 7 + 154 дает одинаковоерезультат как добавление 154 + 7 ...

Альтернативное переопределение этого метода?

Ответы [ 2 ]

3 голосов
/ 06 октября 2011

Во-первых, хотя избегать столкновений - это хорошо, это не проблема, если есть столкновения.Но общий подход - это что-то вроде:

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

Это более заметно, например, в точке / положении, где было бы неплохо избежать очевидных диагональных столкновений, таких как (2,3) против (3)., 2).

A намного большая проблема в вашем коде состоит в том, что свойства в хэш / равно являются изменяемыми;если они будут изменены, любое использование словарей и т. д. перестанет работать.Вы должны предпочитать значения ключей только для чтения.

0 голосов
/ 06 октября 2011

MSDN дает свой вариант ответа для этого случая здесь (в разделе примера):

http://msdn.microsoft.com/en-us/library/bb338049.aspx

Public Class Product
    Public Property Name As String
    Public Property Code As Integer
End Class

' Custom comparer for the Product class
Public Class ProductComparer
    Implements IEqualityComparer(Of Product)

    Public Function Equals1(
        ByVal x As Product, 
        ByVal y As Product
        ) As Boolean Implements IEqualityComparer(Of Product).Equals

        ' Check whether the compared objects reference the same data.
        If x Is y Then Return True

        'Check whether any of the compared objects is null.
        If x Is Nothing OrElse y Is Nothing Then Return False

        ' Check whether the products' properties are equal.
        Return (x.Code = y.Code) AndAlso (x.Name = y.Name)
    End Function

    Public Function GetHashCode1(
        ByVal product As Product
        ) As Integer Implements IEqualityComparer(Of Product).GetHashCode

        ' Check whether the object is null.
        If product Is Nothing Then Return 0

        ' Get hash code for the Name field if it is not null.
        Dim hashProductName = 
            If(product.Name Is Nothing, 0, product.Name.GetHashCode())

        ' Get hash code for the Code field.
        Dim hashProductCode = product.Code.GetHashCode()

        ' Calculate the hash code for the product.
        Return hashProductName Xor hashProductCode ' here.....................
    End Function
End Class
...