/ / Posso depender dos valores de GetHashCode () para ser consistente? - c #, hash

Posso depender dos valores de GetHashCode () para ser consistente? - c #, hash

O valor de retorno de GetHashCode () é garantido consistente, assumindo que o mesmo valor de sequência esteja sendo usado? (C # / ASP.NET)

Fiz upload do meu código em um servidor hoje e, para minha surpresa, tive que reindexar alguns dados porque meu servidor (win2008 de 64 bits) estava retornando valores diferentes em comparação ao meu computador desktop.

Respostas:

29 para resposta № 1

Se não me engano, GetHashCode é consistente com o mesmo valor, mas NÃO é garantido que seja consistente nas diferentes versões da estrutura.

Nos documentos do MSDN em String.GetHashCode ():

O comportamento do GetHashCode depende de suaimplementação, que pode mudar de uma versão do Common Language Runtime para outra. Uma razão pela qual isso pode acontecer é melhorar o desempenho do GetHashCode.


10 para resposta № 2

Eu tive um problema semelhante onde preenchi um banco de dadostabela com informações que dependiam de String.GetHashCode (não é a melhor ideia) e quando atualizei o servidor em que estava trabalhando para x64, notei que os valores que eu estava obtendo de String.GetHashCode eram inconsistentes com o que já estava na tabela. Minha solução foi usar minha própria versão do GetHashCode, que retorna o mesmo valor que String.GetHashCode em uma estrutura x86.

Aqui está o código, não se esqueça de compilar com "Permitir código não 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));
}
}

5 para resposta № 3

A implementação depende da versão da estrutura, mas também depende da arquitetura. A implementação de string.GetHashCode () é diferente nas versões x86 e x64 da estrutura, mesmo que elas tenham o mesmo número de versão.


1 para resposta № 4
    /// <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;
}

Essa implementação pode ser mais lenta que a insegura postada anteriormente. Mas muito mais simples e seguro.


0 para a resposta № 5

Gostaria de saber se há diferenças entre os sistemas operacionais de 32 e 64 bits, porque tenho certeza de que meu servidor e o computador doméstico estão executando a mesma versão do .NET

Sempre me cansei de usar GetHashCode (), talvez seja uma boa ideia para mim simplesmente atribuir meu próprio algoritmo de hash. Bem, pelo menos, acabei escrevendo uma rápida página indexada .aspx por causa disso.


0 para a resposta № 6

Você está executando o Win2008 x86 como área de trabalho? Como o Win2008 inclui a versão 2.0.50727.1434, que é uma versão atualizada do 2.0 incluída no Vista RTM.


0 para resposta № 7

O que notamos no entanto, quando um objeto está emuma coleção de hash objeto (uma hashtable, um dicionário etc), quando 2 objetos não são exclusivos mas seus códigos de hash são, o hashcode é usado apenas como uma primeira opção de pesquisa, se houver códigos de hash não exclusivos sendo usado, o operador de igualdade é sempre usado como um retorno a detirmine a igualdade.

É assim que as pesquisas de hash funcionam, certo? Cada bloco contém uma lista de itens com o mesmo código de hash.

Portanto, para encontrar o item correto nessas condições, é realizada uma pesquisa linear usando a comparação de igualdade de valores.

E se sua implementação de hash atingir boa distribuição, essa pesquisa não será necessária, ou seja, um item por intervalo.

Meu entendimento é correto?


0 para a resposta № 8

Não é uma resposta direta à sua pergunta, que Jonas respondeu bem; no entanto, isso pode ser útil se você estiver preocupado com o teste de igualdade em hashes

De nossos testes, dependendo do que você está exigindo com códigos de hash, em C #, os códigos de hash não precisam ser exclusivos para operações de Igualdade. Como exemplo, considere o seguinte:

Tínhamos a necessidade de sobrecarregar os iguaisoperador e, portanto, a função GetHashCode de nossos objetos, à medida que se tornaram voláteis e sem estado, e se originando diretamente de dados, portanto, em um local do aplicativo, é necessário garantir que um objeto seja exibido como igual a outro objeto se foi originário dos mesmos dados, não apenas se fosse a mesma referência. Nossos identificadores de dados exclusivos são Guids.

O operador igual foi fácil de atender, pois acabamos de verificar o Guid do registro (depois de verificar se há nulo).

Infelizmente, o tamanho dos dados do HashCode (sendo umint) depende do sistema operacional e, em nosso sistema de 32 bits, o código hash seria de 32 bits. Matematicamente, quando substituímos a função GetHashCode, é impossível gerar um código de hash exclusivo a partir de um guid maior que 32 bits (observe o inverso, como você traduziria um número inteiro de 32 bits em um guid?).

Em seguida, fizemos alguns testes em que pegamos o Guid como uma string e retornamos o HashCode do Guid, que quase sempre retorna um identificador exclusivo em nossos testes, mas nem sempre.

O que notamos no entanto, quando um objeto está emum objeto de coleção de hash (uma tabela de hashtags, um dicionário etc.), quando 2 objetos não são únicos, mas seus códigos de hash são, o código de hash é usado apenas como uma primeira opção de pesquisa, se houver códigos de hash não exclusivos em uso, o operador de igualdade é sempre usado como um retorno para detirmine a igualdade.

Como eu disse, isso pode ou não ser relevante para a sua situação, mas se for, é uma dica útil.

ATUALIZAR

Para demonstrar, temos um Hashtable:

Chave: Objeto A (Hashcode 1), valor Objeto A1

Chave: Objeto B (Hashcode 1), valor Objeto B1

Chave: Objeto C (Hashcode 1), valor Objeto C1

Chave: Objeto D (Hashcode 2), valor Objeto D1

Chave: Objeto E (Hashcode 3), valor Objeto E1

Quando eu chamo a hashtable para o objeto com ochave do Objeto A, o objeto A1 será retornado após 2 etapas, uma chamada para o código de hash 1 e, em seguida, uma verificação de igualdade no objeto de chave, pois não há uma chave exclusiva com o código de hash 1

Quando eu chamo a hashtable para o objeto com a chave do Objeto D, o objeto D1 será retornado após 1 etapa, uma pesquisa de hash


-1 para resposta № 9

Eu teria que dizer ... você não pode confiar nisso. Por exemplo, se eu executar o arquivo1 através do código hash md5 do c # e copiar e colar o mesmo arquivo em um novo diretório ... o código hash será diferente, mesmo difícil, ele é o mesmo arquivo. Obviamente é a mesma versão .net, a mesma A única coisa que mudou foi o caminho.