GetHashCode для нулевых полей?

Как мне работать с нулевыми полями в функции GetHashCode?

Module Module1
  Sub Main()
    Dim c As New Contact
    Dim hash = c.GetHashCode
  End Sub

  Public Class Contact : Implements IEquatable(Of Contact)
    Public Name As String
    Public Address As String

    Public Overloads Function Equals(ByVal other As Contact) As Boolean _
        Implements System.IEquatable(Of Contact).Equals
      Return Name = other.Name AndAlso Address = other.Address
    End Function

    Public Overrides Function Equals(ByVal obj As Object) As Boolean
      If ReferenceEquals(Me, obj) Then Return True

      If TypeOf obj Is Contact Then
        Return Equals(DirectCast(obj, Contact))
      Else
        Return False
      End If
    End Function

    Public Overrides Function GetHashCode() As Integer
      Return Name.GetHashCode Xor Address.GetHashCode
    End Function
  End Class
End Module

person Shimmy Weitzhandler    schedule 15.03.2010    source источник
comment
XORing не является хорошим способом объединения хэш-кодов. Для более надежного подхода см. stackoverflow.com/questions/263400/   -  person Jeff Yates    schedule 28.07.2011


Ответы (2)


Как предположил Джефф Йейтс, переопределение в ответе даст тот же хэш для (name = null, address = «foo»), что и (name = «foo», address = null). Эти должны быть разными. Как указано в ссылке, что-то похожее на следующее было бы лучше.

public override int GetHashCode()
{
    unchecked // Overflow is fine, just wrap
    {
        int hash = 17;
        hash = hash * 23 + (Name == null ? 0 : Name.GetHashCode());
        hash = hash * 23 + (Address == null ? 0 : Address.GetHashCode());
    }
    return hash;
}

Каков наилучший алгоритм для переопределенной системы. Object.GetHashCode?

person IllNate    schedule 30.01.2017
comment
(Name == null ? 0 : Name.GetHashCode()) можно сократить до (Foo?.GetHashCode() ?? 0) в C# 7 - person Adam; 22.05.2019

Как правило, вы проверяете значение null и используете 0 для этой «части» хэш-кода, если поле равно null:

return (Name == null ? 0 : Name.GetHashCode()) ^ 
  (Address == null ? 0 : Address.GetHashCode());

(простите за С#-изм, не уверен в эквиваленте нулевой проверки в VB)

person itowlson    schedule 15.03.2010
comment
НП о «csism». вы только что уточнили, что хеш-код для null равен 0. - person Shimmy Weitzhandler; 15.03.2010
comment
Кстати, если отличительным полем является целое число, могу ли я вернуть само целое число вместо его хэш-кода? будет ли это плохой идеей? то есть вернуть ContactId ^ (Name == null ? 0: Name.GetHashCode) (это int)? - person Shimmy Weitzhandler; 15.03.2010
comment
Единственное требование для хэш-кодов состоит в том, что одинаковые объекты возвращают одинаковые хэш-коды. Поскольку равные целые числа равны, возврат целого числа в виде его собственного хэш-кода в порядке. Действительно, это именно то, что делает Int32.GetHashCode...! - person itowlson; 15.03.2010
comment
XORing не является хорошим способом объединения хэш-кодов. Для более надежного подхода см. stackoverflow.com/questions/263400/ - person Jeff Yates; 28.07.2011
comment
кажется, что Nullable‹T› уже возвращает 0, когда HasValue имеет значение false: msdn.microsoft.com/en-us/library/axk9ks7d(v=vs.110).aspx - person Leon van der Walt; 01.04.2015
comment
@Shimmy Обратите внимание, что во многих (всех?) версиях .NET Framework переопределение GetHashCode(), существующее в System.Int32, просто возвращает само целое число. В этом случае ContactId.GetHashCode() совпадает с просто ContactId, когда тип ContactId равен int. конечно, вы никогда не знаете, изменится ли реализация в будущих версиях .NET. - person Jeppe Stig Nielsen; 31.01.2017