net - orm para c#
¿Cuál es la implementación correcta para GetHashCode() para las clases de entidad? (4)
A continuación se muestra una implementación de muestra de Object.Equals () para una clase base de entidad de la que derivan todas las demás entidades en una aplicación.
Todas las clases de entidad tienen la propiedad Id, que es una int anulable. (Es la clave principal de cualquier tabla a la que corresponda la clase de entidad).
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
return false;
if (base.Equals(obj))
return true;
return Id.HasValue && ((EntityBase) obj).Id.HasValue &&
Id.Value == ((EntityBase) obj).Id.Value;
}
Dada esta implementación de Equals (), ¿cómo implementa correctamente GetHashCode ()?
¿Qué pasa con el uso del tipo como parte del código hash?
¿Sería esta una buena implementación?
public class Foo
{
public int Id { get; set; }
// other properties here
// ......
public override int GetHashCode()
{
int hash = 37;
hash = hash * 23 + typeof(Foo).GetHashCode();
hash = hash * 23 + Id.GetHashCode();
return hash;
}
}
Solo puede implementar GetHashCode()
correctamente si la propiedad Id
es inmutable durante el tiempo de vida de una instancia (o al menos durante el tiempo que debe usarse su hash, como cuando el objeto está en un mapa u otra colección que requiere el hash )
Asumiendo que lo sea, puede simplemente usar el valor de Id
como el hash para todos los valores válidos y luego usar un hash fijo para null. No puedo recordar cuál es el más apropiado para esto, pero supondría un valor aleatorio para nulo (seleccionado al azar antes de la compilación, no en tiempo de ejecución) o el valor mediano de valores válidos de Id
(es decir, a medio camino entre 0 y int. Max).
Si se deriva de algo que ya anula GetHashCode
lo implementaría como:
public override int GetHashCode()
{
unchecked
{
int hash = 37;
hash = hash * 23 + base.GetHashCode();
hash = hash * 23 + Id.GetHashCode();
return hash;
}
}
Un valor nulo de Id devolverá 0 para Id.GetHashCode ().
Si su clase simplemente deriva de Object, simplemente devolvería Id.GetHashCode()
- no desea incluir el object.GetHashCode
Implementación de object.GetHashCode
en su código hash, ya que básicamente termina siendo identidad de objeto.
Tenga en cuenta que su definición de igualdad no será true
si ninguna entidad tiene un Id. Pero se devolverá el mismo código hash de ambos objetos. Es posible que desee considerar cambiar su implementación de Equals.
Sin embargo, lo que Jon Skeet respondió es una buena solución, es posible que desee agregar un bloque de código sin marcar para permitir el desbordamiento de un entero
unchecked
{
int hash = ...;
return hash
}
https://msdn.microsoft.com/en-us/library/khy08726(v=vs.140).aspx
Si no se ha marcado ni desmarcado, el contexto predeterminado depende de factores externos, como las opciones del compilador.
También me gustaría agregar, una vez más, que el uso de base.GetHashCode()
en POCO llamará al objeto predeterminado.GetHashCode. Eso definitivamente no es lo que quieres ...