2011-09-27 12 views
8

¿Cuál podría ser el propósito de la tilde en este bloque de código?¿Cuál es el propósito de la tilde en esta situación?

public override int GetHashCode() 
    { 
     return ~this.DimensionId.Id^this.ElementId.Id; 
    } 

^operador (Referencia de C#) binarios^operadores están predefinidos para los tipos integrales y bool Visual Studio. Para los tipos integrales,^calcula el OR exclusivo en bits de sus operandos. Para los operandos bool,^calcula el operador lógico exclusivo o sus operandos; es decir, el resultado es verdadero si y solo si exactamente uno de sus operandos es verdadero.

~ operador (Referencia de C#) Visual Studio 2010 El operador ~ realiza una operación de complemento bit a bit en su operando, lo cual tiene el efecto de invertir cada bit. Los operadores de complemento bit a bit están predefinidos para int, uint, long y ulong.

El operador ~ (tilde) realiza un complemento bit a bit en su único operando entero. (El operador ~ es por lo tanto un operador unario, como! Y el unario, & y * operadores.) Complementar un número significa cambiar todos los 0 bits a 1 y todos los 1 a 0

¿Qué sería una? razón ¿por qué se usaría en este contexto (en lugar de simplemente excluirlo)?

+0

El operador xor tiende a producir una mala distribución de hash si los valores son pequeños. Voltear los bits puede cambiar eso. Las probabilidades de que esto realmente funcione no son buenas. Multiplicar uno por uno principal y agregar funciona mejor. –

Respuesta

13

Es simplemente una forma de generar un código hash. No soy un gran admirador de los XOR en los códigos hash a menos que desee algo que sea independiente del orden, pero es una forma razonable de pasar bits de una manera razonablemente arbitraria pero repetible.

Básicamente tiene aquí dos valores de 32 bits, que necesita combinar de alguna forma para crear otro valor de 32 bits. El código podría acaban de XOR los valores juntos sin ningún complemento bit a bit:

return DimensionId.Id^ElementId.Id; 

... pero que siempre daría cero para los casos en que ElementId.Id == DimensionId.Id, lo que probablemente no es lo ideal. Por otro lado, ahora siempre terminamos con -1 si las dos identificaciones son las mismas, como se señala en los comentarios (¡doh!). Por otro lado, hace que el par {6, 4} tenga un código hash diferente a {4, 6}, mientras que un XOR simple no ... hace que el orden sea importante, en otras palabras. De nuevo, eso podría ser importante si es probable que sus identificadores reales se extraigan de un grupo relativamente pequeño.

El XOR sí se asegura de que un cambio a cualquier poco en ya sea Identificación hace una diferencia en el código hash final.

Personalmente, normalmente sigo el patrón de Josh Bloch de Java efectivo, p.

unchecked 
{ 
    int hash = 17; 
    hash = hash * 31 + DimensionId.Id; 
    hash = hash * 31 + ElementId.Id; 
    return hash; 
} 

... pero eso es sólo debido a algunas de las propiedades de hash de esa manera , y que no tiene la aplicación que has demostrado "equivocado" en ningún sentido.


Parece que funciona bastante bien a la producción de valores distintos en una serie de escenarios comunes.Obviamente no puede evitar colisiones hash, pero si sus identificaciones se generan realmente a partir de una secuencia de 1, 2, 3 ... entonces esto le irá mejor en las colisiones de la vida real que un XOR. Vi una página web analizar este enfoque y qué números funcionan bien, etc., pero no recuerdo dónde.

+0

Jon Skeet- Completamente Ignorante Pregunta: ¿Cuál es el enfoque alternativo/mejor para XOR en los códigos hash? XOR es la única forma en que sé hacerlo bien. –

+0

@RitchMelton: probablemente estaba poniendo mi código preferido mientras comentabas ... ver el final de mi respuesta. –

+0

@Jon - ¿Eché de menos a estos operadores en C# en profundidad 2nd Ed? En cualquier caso, ¡gracias por la información! –

Cuestiones relacionadas