.net-4.0 gethashcode

.net 4.0 - ¿Por qué estos hashcodes son iguales?



override int gethashcode c# (4)

¿Se encontró con esto al procesar una cantidad bastante grande de datos?

Bienvenido al maravilloso mundo de los códigos hash. Un código hash no es un "identificador único". No puede ser. Hay un número esencialmente infinito de posibles instancias diferentes de ese tipo anónimo, pero solo 2 ^ 32 posibles códigos hash. Así que está garantizado que si creas suficientes objetos, verás algunos duplicados. De hecho, si genera 70,000 de esos objetos al azar, las probabilidades son mejores que el 50% de que dos de ellos tengan el mismo código hash.

Consulte Cumpleaños, Números aleatorios y Códigos Hash , y el artículo vinculado de Wikipedia para obtener más información.

En cuanto a por qué algunas personas no vieron un duplicado y otros lo hicieron, es probable que hayan ejecutado el programa en diferentes versiones de .NET. No se garantiza que el algoritmo para generar códigos hash siga siendo el mismo en todas las versiones o plataformas:

El método GetHashCode para un objeto debe devolver consistentemente el mismo código hash siempre que no haya ninguna modificación en el estado del objeto que determine el valor de retorno del método Equals del objeto. Tenga en cuenta que esto es cierto solo para la ejecución actual de una aplicación, y que se puede devolver un código hash diferente si la aplicación se ejecuta nuevamente .

Esta prueba está fallando:

var hashCode = new { CustomerId = 3354, ServiceId = 3, CmsThematicId = (int?)605, StartDate = (DateTime?)new DateTime(2013, 1, 5), EndDate = (DateTime?)new DateTime(2013, 1, 6) }.GetHashCode(); var hashCode2 = new { CustomerId = 1210, ServiceId = 3, CmsThematicId = (int?)591, StartDate = (DateTime?)new DateTime(2013, 3, 31), EndDate = (DateTime?)new DateTime(2013, 4, 1) }.GetHashCode(); Assert.AreNotEqual(hashCode, hashCode2);

Puedes decirme porque ?


Jim me sugirió (en la sala de chat) que almacene mis parámetros para que cuando muestre mis parámetros, seleccione los que no se usen, y cuando alguien se registre, lo señalo como se usa. Pero es un gran PITA para generar todos los parámetros.

Entonces mi solución es construir un hashcode int64 como este

const long i = -1521134295; return -i * (-i * (-i * (-i * -117147284 + customerId.GetHashCode()) + serviceId.GetHashCode()) + cmsThematicId.GetHashCode()) + startDate.GetHashCode();

Eliminé la fecha de finalización porque su valor dependía de serviceId y startDate, así que no debería haber agregado esto al hashcode en el primer lugar. Lo copié / pegué desde una descompilación de la clase generada. No realicé una colisión si realizo una prueba con 300 000 combinaciones diferentes.


Tu prueba no es valida

Debido a que no se garantiza que los códigos hash sean únicos (ver otras respuestas para una buena explicación), no debe probar la singularidad de los códigos hash.

Al escribir su propio método GetHashCode() , es una buena idea probar la distribución uniforme de entradas aleatorias, pero no por exclusividad. Solo asegúrate de usar suficiente entrada aleatoria para obtener una buena prueba.

La especificación de MSDN en GetHashCode establece específicamente:

Para obtener el mejor rendimiento, una función hash debe generar una distribución aleatoria para todas las entradas.

Esto es todo relativo, por supuesto. Un método GetHashCode() que se usa para poner 100 objetos en un diccionario no necesita ser tan aleatorio como GetHashCode() que coloca 10,000,000 de objetos en un diccionario.


Es increíble que hayas encontrado esta coincidencia.

Las clases anónimas tienen un método GetHashCode() generado que genera un código hash combinando los códigos hash de todas las propiedades.

El cálculo es básicamente esto:

public override int GetHashCode() { return -1521134295 * ( -1521134295 * ( -1521134295 * ( -1521134295 * ( -1521134295 * 1170354300 + CustomerId.GetHashCode()) + ServiceId.GetHashCode()) + CmsThematicId.GetHashCode()) + StartDate.GetHashCode()) + EndDate.GetHashCode(); }

Si cambia alguno de los valores de cualquiera de los campos, el código hash cambia. El hecho de que hayas encontrado dos conjuntos diferentes de valores que obtienen los mismos códigos hash es una coincidencia.

Tenga en cuenta que los códigos hash no son necesariamente únicos. Es imposible decir que los códigos hash siempre serán únicos, ya que puede haber más objetos que códigos hash (aunque eso es un montón de objetos). Los buenos códigos hash proporcionan una distribución aleatoria de valores.

NOTA: Lo anterior es de .NET 4. Diferentes versiones de .NET pueden ser diferentes y Mono es diferente.

Si desea comparar dos objetos para igualdad, utilice .Equals() . Para objetos anónimos, compara cada campo. Una opción aún mejor es usar una restricción NUnit que compare cada campo e informe qué campo difiere. Publiqué una restricción aquí:

https://.com/a/2046566/118703