.net 重写GetHashCode变体
我有一个理论上的类名,它有一个字符串.net 重写GetHashCode变体,.net,vb.net,equality,gethashcode,.net,Vb.net,Equality,Gethashcode,我有一个理论上的类名,它有一个字符串Name和一个intOrder 我需要指出两个名称\u顺序,如果对名称顺序不同,也就是说,或者名称或顺序不同 现在,重写等于没有问题,但我对GetHashCode有一些“问题”: Public Class Name_Order Public Property Name As String Public Property Order As Integer Public Overrides Function Equals(ByVal obj As O
Name
和一个intOrder
我需要指出两个名称\u顺序
,如果对名称顺序不同,也就是说,或者名称或顺序不同
现在,重写等于没有问题,但我对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
在这种情况下,求hashcode的和,留下一个(小但真实的)可能性,即具有不同名称或顺序的两个不同名称_顺序是“相同的”
比如说,添加7
+154
会得到与添加154
+7
相同的结果
该方法的替代替代替代方法?首先,虽然避免碰撞是好的,但如果发生碰撞则不是问题。但一种常见的方法是:
return 7 * x.GetHashCode() + y.GetHashCode();
例如,在一个点/位置上,这一点更为明显,在该点/位置上,最好避免(2,3)vs(3,2)等明显的对角线碰撞
代码中一个更大的问题是hash/equals中的属性是可变的;如果它们被改变,词典等中的任何用法都将停止使用。您应该更喜欢只读键值。MSDN在此处给出了该情况的答案变体(在示例部分):
我做了类似的事情,但也使用了位移位和异或,因为如果添加了许多子数据字段的哈希代码,则可能会使哈希代码数据类型溢出。@Mark Gravel:如果没有…,我如何使用只读属性@serhio在c#中,字段上的“readonly”关键字,或属性的“{get;private set;}”。我想VB有similar@Marc:但我需要能够修改该属性。。。我无法将其设置为只读…@serhio如果您在该属性被用作字典或类似工具中的键后对其进行修改,则会破坏该用法。如中所示:无法再找到该项。哈希代码冲突是不可避免的,因为只有2^32个整数,但有更多字符串。您只能尝试减少冲突以提高哈希表的性能。简单地
xor
ing哈希代码通常是个坏主意。特别是交换属性的值不会改变哈希代码。这在本例中可能无关紧要,但在许多情况下是相关的。
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