18

¿Cómo trato con campos nulos en la función GetHashCode?GetHashCode en campos nulos?

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 
+0

XORing no es una buena manera de combinar códigos hash. Para un enfoque más robusto, consulte http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode –

Respuesta

3

Como sugirió Jeff Yates, la anulación en la respuesta daría el mismo hash para (nombre = nulo, dirección = "foo") como (nombre = "foo", dirección = nulo). Estos deben ser diferentes. Como se sugiere en el enlace, algo similar a lo siguiente sería 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; 
} 

What is the best algorithm for an overridden System.Object.GetHashCode?

30

Normalmente, se comprueba por nula y utiliza 0 para que "parte" del código hash si el campo es nulo:

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

(perdón por el C# ismo, no está seguro de la nula verificación equivalente en VB)

+0

np sobre el 'csism'. usted acaba de aclarar que el código hash para null es 0. – Shimmy

+0

por cierto, si el campo distintivo es un int, ¿puedo devolver el int en lugar de su código hash? sería una mala idea? es decir, return ContactId^(Name == null? 0: Name.GetHashCode) (es un int)? – Shimmy

+2

El único requisito para los códigos hash es que los objetos iguales devuelven los mismos códigos hash. Como los iguales son iguales, devolver el int como su propio código hash está bien. De hecho, esto es exactamente lo que parece hacer Int32.GetHashCode ...! – itowlson