2008-09-19 11 views
124

Al igual que muchos de ustedes, uso ReSharper para acelerar el proceso de desarrollo. Cuando lo utiliza para anular los miembros de igualdad de una clase, el código de generación se produce para GetHashCode() se parece a:¿Por qué se usa '397' para la anulación de ReSharper GetHashCode?

public override int GetHashCode() 
    { 
     unchecked 
     { 
      int result = (Key != null ? Key.GetHashCode() : 0); 
      result = (result * 397)^(EditableProperty != null ? EditableProperty.GetHashCode() : 0); 
      result = (result * 397)^ObjectId; 
      return result; 
     } 
    } 

Por supuesto que tengo algunos de mis propios miembros allí, pero lo que estoy queriendo saber es por qué 397?

  • EDIT: Así que mi pregunta estaría mejor redactada ya que, ¿hay algo "especial" sobre el número primo 397 fuera de ser un número primo?

Respuesta

134

Probablemente porque 397 es un primo de tamaño suficiente como para causar que la variable de resultado se desborde y mezclar los bits del hash, proporcionando una mejor distribución de los códigos hash. No hay nada especial en 397 que lo distinga de otros primos de la misma magnitud.

+59

Y 397 está contento. ¿No todos queremos ser felices? –

+2

Bien, pero ¿por qué tiene que ser primordial, y por qué tiene que ser de esa magnitud exacta? Si tiene que ser primordial, ¿por qué no 2 o 2147483647? Supongo que para obtener una buena mutación (y la única razón para esta multiplicación es la mutación) no necesitamos que el número sea primo. Necesitamos que el multiplicador tenga relativamente el mismo número o ceros y unos, preferiblemente sin patrones explícitos. 397 = 110001101b cumple. Todavía no estoy seguro acerca de la magnitud. –

+4

Como dijo Nick, no hay nada particularmente especial al respecto. No NECESITA tener ese tamaño, es solo un número lo suficientemente grande como para que cuando se calcula un hash el resultado se desborde (ya que GetHashCode() devuelve un Int32). Seleccionar un primo es útil para la distribución, no tengo un título en matemáticas, así que no voy a tratar de explicarlo, pero la multiplicación por un primo tendrá un resultado que está más bien distribuido que la multiplicación por cualquier otro número arbitrario. –

15

Ben es correcto, reflejando el Ensamblaje se puede ver que es solo un número primo que han elegido usar.

+8

¿Qué ensamblaje? –

+9

asm: método 'JetBrains.ReSharper.Feature.Services.CSharp':' CSharpEqualityHelper.GenerateGetHashCodeBody' –

6

El hash que usa el reafilador parece una variante del hash FNV. FNV se implementa con frecuencia con diferentes números primos. Hay una discusión sobre la elección apropiada de primos para FNV here.

Cuestiones relacionadas