sirven - metodos accesores c#
¿Puedo depender de los valores de GetHashCode() para ser consistente? (9)
Si no me equivoco, GetHashCode es coherente dado el mismo valor, pero NO se garantiza que sea coherente en las diferentes versiones del marco.
Desde los documentos de MSDN en String.GetHashCode ():
El comportamiento de GetHashCode depende de su implementación, que puede cambiar de una versión del tiempo de ejecución de lenguaje común a otra. Una razón por la que esto podría suceder es mejorar el rendimiento de GetHashCode.
¿Se garantiza que el valor de retorno de GetHashCode () será constante suponiendo que se está utilizando el mismo valor de cadena? (C # / ASP.NET)
Cargué mi código en un servidor hoy y para mi sorpresa tuve que reindexar algunos datos porque mi servidor (win2008 de 64 bits) devolvía valores diferentes en comparación con mi computadora de escritorio.
Lo que notamos sin embargo, cuando un objeto está en un objeto de recolección hash (una tabla hash, un diccionario, etc.), cuando 2 objetos no son únicos sino sus códigos hash, el código hash solo se usa como primera búsqueda de opciones, si no hay -se utilizan códigos hash únicos, el operador de igualdad siempre se utiliza como un retroceso para desviar la igualdad.
Esta es la forma en que las búsquedas de hash funcionan, ¿verdad? Cada segmento contiene una lista de elementos que tienen el mismo código hash.
Entonces, para encontrar el ítem correcto bajo estas condiciones, se lleva a cabo una búsqueda lineal usando la comparación de igualdad de valores.
Y si su implementación de hash logra una buena distribución, esta búsqueda no es necesaria, es decir, un elemento por segmento.
Es mi entendimiento correcto?
¿Estás ejecutando Win2008 x86 como tu escritorio? Porque Win2008 incluye la versión 2.0.50727.1434 , que es una versión actualizada de 2.0 incluida en Vista RTM.
Me pregunto si hay diferencias entre los sistemas operativos de 32 bits y de 64 bits, porque estoy seguro de que tanto mi servidor como la computadora de mi casa están ejecutando la misma versión de .NET
Siempre he estado cansado de usar GetHashCode (), podría ser una buena idea que simplemente represente mi propio algoritmo hash. Bueno, al menos terminé escribiendo una página rápida de re-indexar .aspx por eso.
No es una respuesta directa a su pregunta, que Jonas ha respondido bien, sin embargo, esto puede ser de ayuda si está preocupado por las pruebas de igualdad en hash.
Según nuestras pruebas, dependiendo de lo que requiera con códigos hash, en C #, los códigos hash no necesitan ser únicos para las operaciones de igualdad. Como ejemplo, considere lo siguiente:
Tuvimos el requerimiento de sobrecargar el operador igual, y por lo tanto la función GetHashCode de nuestros objetos ya que se volvieron volátiles y sin estado, y se abastecían directamente de los datos, por lo que en un lugar de la aplicación necesitábamos asegurar que un objeto sería visto como igual a otro objeto si proviene de los mismos datos , no solo si se trata de la misma referencia. Nuestros identificadores de datos únicos son Guids.
El operador de iguales fue fácil de atender, ya que solo verificamos en el Guid del registro (después de verificar nulo).
Desafortunadamente, el tamaño de los datos HashCode (que es un int) depende del sistema operativo, y en nuestro sistema de 32 bits, el código hash sería de 32 bits. Matemáticamente, cuando anulamos la función GetHashCode, es imposible generar un hashcode exclusivo a partir de un guid que sea mayor que 32 bit (míralo desde el inverso, ¿cómo traducirías un entero de 32 bits a un guid?).
Luego hicimos algunas pruebas en las que tomamos el Guid como una cadena y devolvimos el HashCode del Guid, que casi siempre devuelve un identificador único en nuestras pruebas, pero no siempre.
Lo que notamos sin embargo, cuando un objeto está en un objeto de recolección hash (una tabla hash, un diccionario, etc.), cuando 2 objetos no son únicos sino sus códigos hash, el código hash solo se usa como primera búsqueda de opciones, si no hay -se utilizan códigos hash únicos, el operador de igualdad siempre se utiliza como un retroceso para desviar la igualdad .
Como dije, esto puede o no ser relevante para su situación, pero si lo es, es un consejo útil.
ACTUALIZAR
Para demostrar, tenemos una Hashtable:
Clave: Objeto A (Hashcode 1), valor Objeto A1
Clave: Objeto B (Hashcode 1), valor Objeto B1
Clave: Objeto C (Hashcode 1), valor Objeto C1
Clave: Objeto D (Hashcode 2), valor Objeto D1
Clave: Objeto E (Hashcode 3), valor Objeto E1
Cuando llamo a la tabla hash para el objeto con la clave del Objeto A, el objeto A1 se devolverá después de 2 pasos, una llamada para hashcode 1, luego una comprobación de igualdad en el objeto clave ya que no hay una clave única con el código hash 1
Cuando llamo a la tabla hash para el objeto con la clave del Objeto D, el objeto D1 se devolverá después de 1 paso, una búsqueda hash
La implementación depende de la versión del marco pero también depende de la arquitectura . La implementación de string.GetHashCode () es diferente en las versiones x86 y x64 del marco, incluso si tienen el mismo número de versión.
Tuve un problema similar cuando llené una tabla de base de datos con información que dependía de String.GetHashCode (No era la mejor idea) y cuando actualicé el servidor en el que estaba trabajando x64 noté que los valores que obtenía de String.GetHashCode eran inconsistente con lo que ya estaba en la mesa. Mi solución fue usar mi propia versión de GetHashCode, que devuelve el mismo valor que String.GetHashCode en un marco x86.
Aquí está el código, no te olvides de compilar con "Permitir código no seguro":
/// <summary>
/// Similar to String.GetHashCode but returns the same as the x86 version of String.GetHashCode for x64 and x86 frameworks.
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static unsafe int GetHashCode32(string s)
{
fixed (char* str = s.ToCharArray())
{
char* chPtr = str;
int num = 0x15051505;
int num2 = num;
int* numPtr = (int*)chPtr;
for (int i = s.Length; i > 0; i -= 4)
{
num = (((num << 5) + num) + (num >> 0x1b)) ^ numPtr[0];
if (i <= 2)
{
break;
}
num2 = (((num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr[1];
numPtr += 2;
}
return (num + (num2 * 0x5d588b65));
}
}
Tendría que decir ... no puedes confiar en eso. Por ejemplo, si ejecuto el archivo 1 a través del código hash md5 de c # y copio nd y pego el mismo archivo en un nuevo directorio ... el código hash sale diferente aunque sea el mismo archivo. Obviamente es la misma versión .net, mismo todo. Lo único que cambió fue el camino.
/// <summary>
/// Default implementation of string.GetHashCode is not consistent on different platforms (x32/x64 which is our case) and frameworks.
/// FNV-1a - (Fowler/Noll/Vo) is a fast, consistent, non-cryptographic hash algorithm with good dispersion. (see http://isthe.com/chongo/tech/comp/fnv/#FNV-1a)
/// </summary>
private static int GetFNV1aHashCode(string str)
{
if (str == null)
return 0;
var length = str.Length;
// original FNV-1a has 32 bit offset_basis = 2166136261 but length gives a bit better dispersion (2%) for our case where all the strings are equal length, for example: "3EC0FFFF01ECD9C4001B01E2A707"
int hash = length;
for (int i = 0; i != length; ++i)
hash = (hash ^ str[i]) * 16777619;
return hash;
}
Esta implementación puede ser más lenta que la insegura publicada anteriormente. Pero mucho más simple y seguro.