重写 GetHashCode 变体

发布于 2024-12-08 16:14:29 字数 1036 浏览 3 评论 0原文

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

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

现在,覆盖 Equals 没有问题,但我对 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 得到的结果相同...

另一种覆盖那个方法?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

层林尽染 2024-12-15 16:14:29

首先,虽然避免碰撞固然很好,但如果发生碰撞也不是问题。但常见的方法是这样的:

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

这在例如点/位置中更为明显,最好避免明显的对角线碰撞,例如 (2,3) 与 (3,2)。

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

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.

九公里浅绿 2024-12-15 16:14:29

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

MSDN gives its variant of the answer for that case here (in the Example's section):

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文