GetHashCode Método
Este artigo foi traduzido por máquina. Coloque o ponteiro do mouse sobre as frases do artigo para ver o texto original. Mais informações.
Tradução
Original

Método Object.GetHashCode ()

 

Serve como a função de hash para um tipo específico.

Namespace:   System
Assembly:  mscorlib (em mscorlib.dll)

public virtual int GetHashCode()

Valor de retorno

Type: System.Int32

Um código hash do objeto atual.

Um código de hash é um valor numérico que é usado para inserir e identificar um objeto em uma coleção baseada em hash, como o Dictionary<TKey, TValue> classe, a Hashtable classe ou um tipo derivado da DictionaryBase classe.O GetHashCode método fornece esse código hash para algoritmos que precisam de verificações rápidas de igualdade do objeto.

System_CAPS_noteObservação

Para obter informações sobre como os códigos de hash são usados em tabelas de hash e alguns algoritmos de código hash adicionais, consulte o Hash Function entrada na Wikipedia.

Dois objetos são códigos de hash igual de retorno são iguais.No entanto, o inverso não é verdadeiro: códigos hash igual não implicam igualdade de objetos, como objetos (diferentes) diferentes podem ter códigos hash idênticos.Além disso, o .NET Framework não garante a implementação padrão do GetHashCode método e o valor que este método retorna podem diferir entre versões do .NET Framework e plataformas, como plataformas de 32 bits e 64 bits.Por esses motivos, não use a implementação padrão desse método como um identificador exclusivo do objeto para fins de hash.Execute as duas conseqüências deste:

  • Você não deve supor que códigos hash igual implicam igualdade do objeto.

  • Você nunca deve persistir ou usar um código hash fora do domínio de aplicativo no qual ele foi criado, pois o mesmo objeto pode hash entre plataformas, processos e domínios de aplicativo.

System_CAPS_warningAviso

Um código hash destina-se a inserção eficiente e de pesquisa em conjuntos com base em uma tabela de hash.Um código de hash não é um valor permanente.Por esse motivo:

  • Não serializar valores de código de hash ou armazená-las em bancos de dados.

  • Não use o código de hash como a chave para recuperar um objeto de uma coleção chaveada.

  • Não envie códigos hash entre domínios de aplicativos ou processos.Em alguns casos, códigos hash podem ser computados em uma base por processo ou por aplicativos de domínio.

  • Não use o código de hash em vez de um valor retornado por uma função de hash criptográfica se precisar de um hash criptograficamente forte.Para hashes criptográficos, usar uma classe que deriva de System.Security.Cryptography.HashAlgorithm ou System.Security.Cryptography.KeyedHashAlgorithm classe.

  • Testa a igualdade de códigos de hash para determinar se dois objetos são iguais.(Objetos diferentes podem ter códigos hash idênticos.) Para testar a igualdade, chame o ReferenceEquals ou Equals método.

O GetHashCode método pode ser substituído por um tipo derivado.Se GetHashCode é não substituído, códigos hash para tipos de referência são computados ao chamar o Object.GetHashCode método da classe base, que calcula um código hash com base na referência do objeto; para obter mais informações, consulte RuntimeHelpers.GetHashCode.Em outras palavras, dois objetos para os quais o ReferenceEquals retorn true ter códigos hash idênticos.Se os tipos de valor não substituir GetHashCode, o ValueType.GetHashCode método da classe base usa a reflexão para calcular o código hash com base nos valores dos campos do tipo.Em outras palavras, tipos de valor cujos campos com valores iguais têm códigos hash igual.Para obter mais informações sobre como substituir GetHashCode, consulte a seção "Observações para Herdeiros".

System_CAPS_warningAviso

Se você substituir o GetHashCode método, também deverá substituir Equals, e vice-versa.Se seu substituído Equals retorn true quando dois objetos são testados para igualdade, seu substituída GetHashCode método deve retornar o mesmo valor para os dois objetos.

Se um objeto que é usado como uma chave em uma tabela de hash não fornece uma implementação útil de GetHashCode, você pode especificar um provedor de código de hash, fornecendo uma IEqualityComparer uma das sobrecargas de implementação a Hashtable construtor da classe.

Quando você chama o GetHashCode método em uma classe a Tempo de Execução do Windows, ele fornece o comportamento padrão para classes não substituem GetHashCode.Ele faz parte do suporte que o .NET Framework dá para o Tempo de Execução do Windows (consulte Suporte do .NET Framework para aplicativos da Windows Store e Tempo de Execução do Windows).Classes de Tempo de Execução do Windows não herdam Object, e atualmente não implementar um GetHashCode.No entanto, eles parecem ter ToString, Equals(Object), e GetHashCode métodos quando usá-los em seu código c# ou Visual Basic e o .NET Framework fornece o comportamento padrão para esses métodos.

System_CAPS_noteObservação

Tempo de Execução do Windows as classes que são escritas em c# ou Visual Basic podem substituir o GetHashCode método.

Observações para herdeiros:

Uma função de hash é usada para gerar rapidamente um número (código de hash) que corresponde ao valor de um objeto.Funções de hash são geralmente específicas de cada tipo e, de exclusividade, devem usar pelo menos um dos campos de instância como entrada.Códigos de hash não devem ser calculados usando os valores de campos estáticos.

Para classes derivadas de Object, o GetHashCode método pode delegar para a classe base Object.GetHashCode() implementação somente se a classe derivada define igualdade para igualdade de referência.A implementação padrão de GetHashCode para referência tipos retorna um código de hash que é equivalente ao retornado pelo RuntimeHelpers.GetHashCode(Object) método.Você pode substituir GetHashCode para tipos de referência imutável.Em geral, para tipos de referência mutáveis, você deve substituir GetHashCode somente se:

  • Você pode calcular o código hash de campos que não são mutáveis; ou

  • Você pode garantir que o código hash de um objeto mutável não altera enquanto o objeto está contido em uma coleção que se baseia em seu código de hash.

Caso contrário, talvez você pense que o objeto mutável é perdido na tabela de hash.Se você optar por substituir GetHashCode para um tipo de referência mutáveis, a documentação deve deixar claro que os usuários do seu tipo não devem modificar valores de objeto enquanto o objeto está armazenado em uma tabela de hash.

Para tipos de valor, ValueType.GetHashCode fornece uma implementação de código de hash padrão que usa a reflexão.Considere a possibilidade de substituí-lo para melhorar o desempenho.

System_CAPS_noteObservação

Para obter mais informações e exemplos de códigos de hash em uma variedade de formas de computação, consulte a seção exemplos.

Uma função de hash deve ter as seguintes propriedades:

  • Se dois objetos são comparados como iguais, o GetHashCode método para cada objeto deve retornar o mesmo valor.No entanto, se dois objetos não comparados como iguais, o GetHashCode métodos para os dois objetos não precisam retornar valores diferentes.

  • O GetHashCode método de um objeto consistentemente deve retornar o mesmo código de hash, desde que não há nenhuma modificação para o estado do objeto que determina o valor de retorno do objeto Equals método.Observe que isso vale apenas para a execução atual de um aplicativo e que um código hash diferente pode ser retornado se o aplicativo for executado novamente.

  • Para melhor desempenho, uma função de hash deve gerar uma distribuição uniforme para todas as entradas, incluindo entrada intensamente em cluster.Uma implicação é que pequenas modificações para o estado do objeto devem resultar em grandes modificações no código de hash resultante para melhor desempenho de tabela de hash.

  • Funções de hash devem ser acessíveis para computação.

  • O GetHashCode método não deve lançar exceções.

Por exemplo, a implementação do GetHashCode método fornecido pelo String classe retorna códigos de hash idênticos para valores de cadeia de caracteres idêntica.Portanto, dois String objetos retornam o mesmo código hash se eles representam o mesmo valor de cadeia de caracteres.Além disso, o método usa todos os caracteres na cadeia de caracteres para gerar saída distribuída razoavelmente aleatoriamente, mesmo quando a entrada for clusterizada em determinados intervalos (por exemplo, muitos usuários podem ter cadeias de caracteres que contêm apenas inferior 128 caracteres ASCII, embora uma cadeia de caracteres pode conter nenhum dos caracteres Unicode 65.535).

Fornecer uma boa função de hash em uma classe pode afetar significativamente o desempenho de adicionar esses objetos a uma tabela de hash.Em uma tabela de hash com chaves que fornecem uma boa implementação de uma função de hash, procurando por um elemento leva tempo constante (por exemplo, uma operação (1)).Em uma tabela de hash com uma implementação inadequada de uma função de hash, o desempenho de uma pesquisa depende do número de itens na tabela de hash (por exemplo, um O (n) operação, onde n é o número de itens na tabela de hash).Um usuário mal-intencionado pode inserir dados que aumenta o número de conflitos, o que pode afetar significativamente o desempenho de aplicativos que dependem de tabelas de hash, sob as seguintes condições:

  • Quando as funções de hash produzem colisões freqüentes.

  • Quando uma grande proporção de objetos em uma tabela de hash produzir códigos de hash são iguais ou aproximadamente iguais entre si.

  • Quando os usuários entrada de dados do qual o código de hash é calculado.

As classes derivadas que substituem GetHashCode também deve substituir Equals para garantir que dois objetos considerados iguais têm o mesmo código hash; caso contrário, o Hashtable tipo talvez não funcionem corretamente.

Uma das maneiras mais simples para calcular um código hash para um valor numérico que tem o mesmo ou um intervalo menor que o Int32 tipo é simplesmente retornar esse valor.O exemplo a seguir mostra esse uma implementação para um Number estrutura.

using System;

public struct Number
{
   private int n;

   public Number(int value)
   {
      n = value;
   }

   public int Value
   {
      get { return n; }
   }

   public override bool Equals(Object obj)
   {
      if (obj == null || ! (obj is Number)) 
         return false;
      else
         return n == ((Number) obj).n;
   }      

   public override int GetHashCode()
   {
      return n;
   }

   public override string ToString()
   {
      return n.ToString();
   }
}

public class Example
{
   public static void Main()
   {
      Random rnd = new Random();
      for (int ctr = 0; ctr <= 9; ctr++) {
         int randomN = rnd.Next(Int32.MinValue, Int32.MaxValue);
         Number n = new Number(randomN);
         Console.WriteLine("n = {0,12}, hash code = {1,12}", n, n.GetHashCode());
      }   
   }
}
// The example displays output like the following:
//       n =   -634398368, hash code =   -634398368
//       n =   2136747730, hash code =   2136747730
//       n =  -1973417279, hash code =  -1973417279
//       n =   1101478715, hash code =   1101478715
//       n =   2078057429, hash code =   2078057429
//       n =   -334489950, hash code =   -334489950
//       n =    -68958230, hash code =    -68958230
//       n =   -379951485, hash code =   -379951485
//       n =    -31553685, hash code =    -31553685
//       n =   2105429592, hash code =   2105429592

Frequentemente, um tipo possui vários campos de dados que podem participar de gerar o código hash.Uma maneira de gerar um código hash é combinar esses campos usando um XOR (eXclusive OR) operação, conforme mostrado no exemplo a seguir.

using System;

// A type that represents a 2-D point.
public struct Point
{
    private int x;
    private int y;

    public Point(int x, int y)
    {
       this.x = x;
       this.y = y;
    }

    public override bool Equals(Object obj)
    {
       if (! (obj is Point)) return false;

       Point p = (Point) obj;
       return x == p.x & y == p.y;
    }

    public override int GetHashCode()
    { 
        return x ^ y;
    } 
} 

public class Example
{
   public static void Main()
   {
      Point pt = new Point(5, 8);
      Console.WriteLine(pt.GetHashCode());

      pt = new Point(8, 5);
      Console.WriteLine(pt.GetHashCode());
   }
}
// The example displays the following output:
//       13
//       13

O exemplo anterior retorna o mesmo código hash para (n1, n2) e (n2, n1) e, portanto, pode gerar mais colisões de desejáveis.Várias soluções estão disponíveis para que os códigos de hash nesses casos não são idênticos.Uma é para retornar o código hash de uma Tuple objeto que reflete a ordem de cada campo.O exemplo a seguir mostra uma possível implementação usa a Tuple<T1, T2> classe.Observe, porém, que a sobrecarga de desempenho de instanciar um Tuple objeto pode afetar significativamente o desempenho geral de um aplicativo que armazena o grande número de objetos em tabelas de hash.

using System;

public struct Point
{
    private int x;
    private int y;

    public Point(int x, int y)
    {
       this.x = x;
       this.y = y;
    }

    public override bool Equals(Object obj)
    {
       if (!(obj is Point)) return false;

       Point p = (Point) obj;
       return x == p.x & y == p.y;
    }

    public override int GetHashCode()
    { 
        return Tuple.Create(x, y).GetHashCode();
    } 
} 

public class Example
{
   public static void Main()
   {
        Point pt = new Point(5, 8);
        Console.WriteLine(pt.GetHashCode());

        pt = new Point(8, 5);
        Console.WriteLine(pt.GetHashCode());
   }
}
// The example displays the following output:
//       173
//       269

Uma segunda solução alternativa envolve a importância dos códigos de hash individuais mudando esquerda os códigos de hash de campos sucessivos por dois ou mais bits.Ideal, em vez de ser descartado, bits deslocados além de 31 bits devem ser disposto em torno em vez de ser descartados.Como os bits são descartados pelos operadores shift esquerda em c# e Visual Basic, isso requer criando um método de codificação shift esquerdo semelhante ao seguinte:

public int ShiftAndWrap(int value, int positions)
{
    positions = positions & 0x1F;

    // Save the existing bit pattern, but interpret it as an unsigned integer.
    uint number = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
    // Preserve the bits to be discarded.
    uint wrapped = number >> (32 - positions);
    // Shift and wrap the discarded bits.
    return BitConverter.ToInt32(BitConverter.GetBytes((number << positions) | wrapped), 0);
}

O exemplo a seguir usa esse método de codificação shift para calcular o código hash do Point estrutura usada nos exemplos anteriores.

using System;

public struct Point
{
    private int x;
    private int y;

    public Point(int x, int y)
    {
       this.x = x;
       this.y = y;
    }

    public override bool Equals(Object obj)
    {
       if (!(obj is Point)) return false;

       Point p = (Point) obj;
       return x == p.x & y == p.y;
    }

    public override int GetHashCode()
    { 
        return ShiftAndWrap(x.GetHashCode(), 2) ^ y.GetHashCode();
    } 

    private int ShiftAndWrap(int value, int positions)
    {
        positions = positions & 0x1F;

        // Save the existing bit pattern, but interpret it as an unsigned integer.
        uint number = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
        // Preserve the bits to be discarded.
        uint wrapped = number >> (32 - positions);
        // Shift and wrap the discarded bits.
        return BitConverter.ToInt32(BitConverter.GetBytes((number << positions) | wrapped), 0);
    }
} 

public class Example
{
   public static void Main()
   {
        Point pt = new Point(5, 8);
        Console.WriteLine(pt.GetHashCode());

        pt = new Point(8, 5);
        Console.WriteLine(pt.GetHashCode());
   }
}
// The example displays the following output:
//       28
//       37 

Universal Windows Platform
Disponível desde 4.5
.NET Framework
Disponível desde 1.1
Portable Class Library
Com suporte em: portable .NET platforms
Silverlight
Disponível desde 2.0
Windows Phone Silverlight
Disponível desde 7.0
Windows Phone
Disponível desde 8.1
Retornar ao topo
Mostrar:
© 2016 Microsoft