创建可比较的词典键

时间:2010-08-30 16:03:14

标签: c# vb.net collections dictionary

我想使用Dictionary(Of Key,Value),Key不是基类型,而是类:

Public Class MyKey

    Sub New(ByVal packet As String, ByVal sent As Boolean)
        Me.packet = packet.ToUpper.Trim
        Me.sent = sent
    End Sub

    Private packet As String
    Private sent As Boolean
End Class

现在要让Dictionary工作并找到键,我必须在Key类中实现System.IEquatable接口(或使用不同的构造函数,但这是另一个故事):

Public Class MyKey
    Implements System.IEquatable(Of MyKey)


    Sub New(ByVal packet As String, ByVal sent As Boolean)
        Me.packet = packet.ToUpper.Trim
        Me.sent = sent
    End Sub

    Public Overloads Function Equals(ByVal other As MyKey) As Boolean Implements IEquatable(Of MyKey).Equals
        Return other.sent = Me.sent AndAlso other.packet = Me.packet
    End Function


    Private packet As String
    Private sent As Boolean
End Class

但是要获得一致的结果,我还要实现Object.Equals和Object.GetHashCode:

Public Class MyKey
    Implements System.IEquatable(Of MyKey)


    Sub New(ByVal packet As String, ByVal sent As Boolean)
        Me.packet = packet.ToUpper.Trim
        Me.sent = sent
    End Sub

    Public Overloads Function Equals(ByVal other As ChiavePietanza) As Boolean Implements IEquatable(Of MyKey).Equals
        Return other.sent = Me.sent AndAlso other.packet = Me.packet
    End Function

    Overrides Function Equals(ByVal o As Object) As Boolean
        Dim cast As MyKey = DirectCast(o, MyKey)
        Return Equals(cast)
    End Function

    Public Overrides Function GetHashCode() As Integer
        Return packet.GetHashCode Or sent.GetHashCode
    End Function


    Private packet As String
    Private sent As Boolean
End Class

问题是:GetHashCode实现是否正确?我应该如何实现它,返回一个哈希码,它将字符串和布尔哈希码合并?

4 个答案:

答案 0 :(得分:4)

您的GetHashCode函数是正确的,并且符合已知的哈希代码实现规则。特别是

  • MyKey
  • 的等效实例的值相同
  • MyKey
  • 的更改不会改变

虽然可以做得更好的一种方法是让packetsent成为ReadOnly字段。现在暗示它们是ReadOnly因为它们在GetHashCode函数中使用。但是,未来的开发人员可能会忽略这一点,改变值并破坏GetHashCode所需的合同。明确地ReadOnly使用它们可以防止意外中断。

另一个小调。虽然为IEquatable(Of T)密钥实施Dictionary是个好主意,但这不是必需的。所需要的只是覆盖EqualsGetHashCode方法,以使密钥在Dictionary中正常运行。

答案 1 :(得分:2)

它很好,但是Or运算符不会生成分布均匀的哈希值,因为它只能打开位而不能关闭。请改用Xor运算符。

答案 2 :(得分:2)

本文是我所有GetHashCode覆盖的基础:

SO - What is the best algorithm for an overridden System.Object.GetHashCode? 所以你可以这样做:

public override int GetHashCode() {
    int hash = 17;
    hash = (hash * 23) + ((packet != null) ? packet.GetHashCode() : 0);
    hash = (hash * 23) + ((sent != null) ? sent.GetHashCode() : 0);
    return hash;
}

应该直接将其移植到VB。

答案 3 :(得分:0)

如果你想要一些简单的东西,并且表现并不重要,我相信结构类型的字典会将两个结构视为相同,如果它们的所有成员都相等。性能不是很好,但代码非常简单。