¿Cómo lidiar con los campos nulos en GetHashCode función?

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
InformationsquelleAutor Shimmy | 2010-03-15

2 Comentarios

  1. 7

    Como Jeff Yates sugerido, el reemplazo en la respuesta que daría el mismo hash (nombre = null, address = «foo») como (name = «foo», dirección = null). Estos deben ser diferentes. Como se sugiere en el enlace, algo similar a lo siguiente será mejor.

    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;
    }
    

    ¿Cuál es el mejor algoritmo para anulado Sistema.Objeto.GetHashCode?

    • (Name == null ? 0 : Name.GetHashCode()) puede ser condensado a (Foo?.GetHashCode() ?? 0) en C# 7
  2. 32

    Normalmente, comprobar el valor null y utilice 0 para que «parte» del código hash de si el campo es nulo:

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

    (perdón por el C#-ismo, no estoy seguro de verificación null equivalente en VB)

    • np acerca de la ‘csism’. sólo aclaró que el código hash de null es 0.
    • por cierto, si la distinción de campo es un int, puedo devolver el int sí mismo, en lugar de la etiqueta? tendría que ser una mala idea? es decir, volver ContactId ^ (Nombre == null ? 0 : Nombre.GetHashCode) (es un int)?
    • El único requisito para códigos hash es que la igualdad de los objetos de retorno de la igualdad de códigos hash. Desde la igualdad de enteros son iguales, devolviendo a la int como su propio código hash es buena. De hecho, esto es exactamente lo que Int32.GetHashCode parece hacer…!
    • gracias, me lo imaginaba pero no estaba seguro, muchas gracias!!!
    • El cifrado xor no es una buena manera de combinar códigos hash. Para una actuación más eficaz, consulte stackoverflow.com/questions/263400/…
    • parece que aceptan valores null<T> ya devuelve 0 cuando HasValue es falsa: msdn.microsoft.com/en-us/library/axk9ks7d(v=vs 110).aspx
    • Tenga en cuenta que en muchos (todos?) versiones de el .NET Framework, la anulación de GetHashCode() que existe en System.Int32 simplemente devuelve el entero en sí mismo. En ese caso ContactId.GetHashCode() es el mismo que ContactId cuando el tipo de ContactId es int. por supuesto, nunca se sabe si la aplicación va a cambiar en futuras versiones de .NET.

Dejar respuesta

Please enter your comment!
Please enter your name here