Exportar (0) Imprimir
Expandir Tudo
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 padrão.

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

public virtual int GetHashCode()

Valor de retorno

Tipo: System.Int32
Um código hash do objeto atual.

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

ObservaçãoObservação

Para obter informações sobre como os códigos de hash são usadas nas tabelas de hash e para alguns algoritmos adicionais de código hash, consulte Função de hash a entrada em Wikipedia.

Dois objetos que são os códigos de hash de retorno é igual a serão iguais. No entanto, o contrário não for verdadeiro: os códigos de hash iguais não implicam a igualdade do objeto, como os objetos diferentes () diferentes podem ter códigos de hash idênticos. Além disso, o .NET Framework não garante a implementação padrão do método de GetHashCode , e o valor esse método retornará pode diferir entre versões do.NET Framework e plataformas, como plataformas de 32 bits e de 64 bits. Por esse motivo, não use a implementação padrão desse método como um identificador de objeto hash exclusivo. Duas consequências seguem esta:

  • Você não deve pressupor que os códigos de hash de igual implicam a igualdade do objeto.

  • Você nunca deve persistir ou usar um código hash fora do domínio de aplicativo em que foi criado, porque o mesmo objeto pode hash pelos domínios de aplicativo, os processos, e as plataformas.

Observação de cuidadoCuidado

Um código hash é destinado para inserção e a pesquisa eficientes nas coleções baseadas em uma tabela de hash. Um código hash não é um valor permanente. Por esse motivo:

  • Não serializar os valores de código de hash ou não armazenar nas bases de dados.

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

  • Não enviar código de hash pelos domínios de aplicativo ou de processos. Em alguns casos, os códigos de hash podem ser computados em uma base de domínio do processo ou do aplicativo.

  • Não use o código hash em vez de um valor retornado por uma função de hash criptográfico se você precisar de um hash criptograficamente forte. Para hash de criptografia, use uma classe derivada da classe de System.Security.Cryptography.HashAlgorithm ou de System.Security.Cryptography.KeyedHashAlgorithm .

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

O método de GetHashCode pode ser substituído por um tipo derivado. Se GetHashCode não for substituído, os códigos de hash para tipos de referência são computados chamando o método de Object.GetHashCode da classe base, que calcula um código hash com base na referência de um objeto; para obter mais informações, consulte RuntimeHelpers.GetHashCode. Ou seja dois objetos para os quais o método de ReferenceEquals retorna true têm códigos de hash idênticos. Se os tipos de valor não substitui GetHashCode, o método de ValueType.GetHashCode da classe base usa a reflexão para computar o código hash com base nos valores dos campos do tipo. Ou seja tipos de valores cujos campos tiverem valores iguais ter códigos de hash iguais. Para obter mais informações sobre como anular GetHashCode, consulte a seção “notas para Inheritors”.

Observação de cuidadoCuidado

Se você substitui o método de GetHashCode , você também deve substituir Equals, e vice-versa. Se o método substituído de Equals retorna true quando dois objetos serão testados para igualdade, o método substituído de GetHashCode deve retornar o mesmo valor para os dois objetos.

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

Observações para o Tempo de Execução do Windows

Quando você chama o método de GetHashCode em uma classe em Tempo de Execução do Windows, fornece o comportamento padrão para classes que não substitui 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). As classes em Tempo de Execução do Windows não herdam Object, e não no momento implementam GetHashCode. No entanto, parecem ter ToString, Equals(Object), e os métodos de GetHashCode quando devem ser usados em seu código C# ou Visual Basic, e o.NET Framework fornece o comportamento padrão para esses métodos.

ObservaçãoObservação

as classes deTempo de Execução do Windows que são gravadas em C# ou no Visual Basic podem substituir o método de GetHashCode .

Observações para herdeiros

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

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

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

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

Caso contrário, você poderá pensar que o objeto é perdido mutável na tabela de hash. Se você escolher substituir GetHashCode para um tipo mutável de referência, a documentação deve esclarecer quais os usuários de seu tipo não devem alterar valores de objetos quando o objeto é armazenado em uma tabela de hash.

Para tipos de valor, ValueType.GetHashCode fornece uma implementação de código hash padrão que usa a reflexão. Você deve considerar substituí-la para melhor desempenho.

ObservaçãoObservação

Para obter mais informações e exemplos que computam código de hash de várias formas, consulte a seção exemplos.

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

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

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

  • Para melhor desempenho, uma função de hash deve gerar uma distribuição uniforme para qualquer entrada, incluindo a entrada que é agrupada peso. Uma implicação é que as modificações pequenas para o estado de objeto devem gerar grandes alterações no código de hash resultante para melhor hash o desempenho.

  • As funções hash devem ser baratas computar.

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

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

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 as chaves que fornecem uma boa implementação de uma função de hash, procurando um tempo constantes de obtidas do elemento (por exemplo, (1) uma operação) do. Em uma tabela de hash com uma implementação ruim de uma função de hash, o desempenho de uma pesquisa depende do número de itens no hash (por exemplo, uma operação den(), onde n é o número de itens na tabela de hash). Um usuário mal-intencionado pode os dados de entrada que aumenta o número de gráfico, que podem afetar o desempenho significativamente os aplicativos que dependem de tabelas de hash, sob as seguintes condições:

  • Quando as funções hash gerencie colisões frequentes.

  • Quando uma grande proporção de objetos em uma tabela de hash os códigos de hash do produto que forem iguais ou aproximadamente igual a outro.

  • Quando os usuários entrarem os dados de que o código hash é computado.

As classes derivadas que substituem GetHashCode também devem substituir Equals para garantir que dois objetos experimentaram igual tenham o mesmo código de hash; caso contrário, o tipo de Hashtable talvez não funcione corretamente.

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


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 tem vários campos de dados que podem participar de gerar o código hash. Uma maneira de gerar um código de hash é combinar esses campos usando uma operação de XOR (eXclusive OR) , 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 das quais é desejável. Um número de soluções estão disponíveis de modo que os códigos de hash não sejam idênticos nesses casos. Um deve retornar o código hash de um objeto de Tuple que reflete a ordem de cada campo. O exemplo a seguir mostra uma possível implementação que use a classe de Tuple<T1, T2> . Observe, entretanto, que a sobrecarga de desempenho de criar uma instância de um objeto de Tuple pode afetar significativamente o desempenho geral de um aplicativo que armazena um 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 envolve pesar os códigos de hash individuais pelo deslocamento deslocamento os códigos de hash de campos sucessivos por dois ou mais bits. Ótima, em vez de rejeição, os bits deslocados além de 31 bits devem incluir o redor de um vez de que é descartado. Desde que os bits são rejeitados pelos operadores de deslocamento turno no C# e em Visual Basic, isso requer a criação de um método esquerdo de SHIFT-e- quebra automática como o 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 seguinte exemplo usa esse método de SHIFT-e- quebra automática para computar o código hash da estrutura de Point 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 


.NET Framework

Com suporte em: 4.5.2, 4.5.1, 4.5, 4, 3.5, 3.0, 2.0, 1.1, 1.0

.NET Framework Client Profile

Com suporte em: 4, 3.5 SP1

Biblioteca de Classes Portátil

Com suporte em: Biblioteca de Classes Portátil

.NET para aplicativos da Windows Store

Com suporte em: Windows 8

.NET para aplicativos do Windows Phone

Com suporte em: Windows Phone 8, Silverlight 8.1

Windows Phone 8.1, Windows Phone 8, Windows 8.1, Windows Server 2012 R2, Windows 8, Windows Server 2012, Windows 7, Windows Vista SP2, Windows Server 2008 (Função Server Core sem suporte), Windows Server 2008 R2 (Função Server Core com suporte com o SP1 ou posterior, Itanium sem suporte)

O .NET Framework não oferece suporte a todas as versões de cada plataforma. Para obter uma lista das versões com suporte, consulte Requisitos do sistema do .NET Framework.

Contribuições da comunidade

ADICIONAR
Mostrar:
© 2014 Microsoft