覆盖GetHashCode变体

时间:2011-10-06 17:03:18

标签: .net vb.net equality gethashcode

我有一个理论类Name_Order,它有一个字符串Name和一个int Order

我需要指出两个Name_Order是不同的,如果NameOrder对不同,那么,或者名称或顺序是不同的。

现在,重写Equals no problemo ,但我对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_Orders是“相同的”。

说,添加7 + 154会产生与添加154 + 7相同的结果......

该方法的替代覆盖?

2 个答案:

答案 0 :(得分:3)

首先,虽然避免冲突是好的,但如果冲突则不是问题。但是一种常见的方法是:

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

这在例如点/位置更明显,避免明显的对角线碰撞会很好,如(2,3)vs(3,2)。

代码中的 很多 更大的问题是hash / equals中的属性是可变的;如果它们被更改,字典中的任何用法都将停止工作。您应该更喜欢只读键值。

答案 1 :(得分:0)

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