Создание сопоставимого словарного ключа - PullRequest
4 голосов
/ 30 августа 2010

Я хочу использовать словарь (Of Key, Value), и ключ - это не базовый тип, а класс вроде:

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

Теперь, чтобы словарь работал и находил ключи,Я должен реализовать интерфейс System.IEquatable в классе Key (или использовать другой конструктор, но это уже другая история):

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 ]

4 голосов
/ 30 августа 2010

Ваша функция GetHashCode верна и соответствует известным правилам реализации хеш-кода. В частности

  • То же самое для значения для эквивалентных экземпляров MyKey
  • Не изменяется с изменениями на MyKey

Единственный способ сделать это лучше - сделать поля packet и sent ReadOnly. Прямо сейчас подразумевается, что они ReadOnly, потому что они используются в функции GetHashCode. Однако будущий разработчик может не заметить этого, изменить значения и разорвать контракт, необходимый для GetHashCode. Их явное ReadOnly предотвращает случайные поломки.

Еще одна небольшая заметка. Хотя реализация ключей IEquatable(Of T) для Dictionary является хорошей идеей, это не является обязательным требованием. Все, что нужно, это переопределить метод Equals и GetHashCode, чтобы ключ работал правильно в Dictionary.

2 голосов
/ 30 августа 2010

В этой статье я базирую все мои GetHashCode переопределения:

SO - Какой лучший алгоритм для переопределенного 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.

2 голосов
/ 30 августа 2010

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

0 голосов
/ 30 августа 2010

Если вам нужно что-то простое, а производительность не критична, я считаю, что словарь структурного типа будет считать две структуры равными, если все их члены равны.Производительность не очень хорошая, но код очень прост.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...