Compartilhar via


Método System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode

Este artigo fornece comentários complementares à documentação de referência para esta API.

O RuntimeHelpers.GetHashCode método sempre chama o Object.GetHashCode método de forma não virtual, mesmo que o tipo do objeto tenha substituído o Object.GetHashCode método. Portanto, usar RuntimeHelpers.GetHashCode pode ser diferente de chamar GetHashCode diretamente no objeto com o método Object.GetHashCode.

Aviso

Embora o RuntimeHelpers.GetHashCode método retorne códigos hash idênticos para referências de objeto idênticas, você não deve usar esse método para testar a identidade do objeto, pois esse código hash não identifica exclusivamente uma referência de objeto. Para testar a identidade do objeto (ou seja, para testar se dois objetos fazem referência ao mesmo objeto na memória), chame o Object.ReferenceEquals método. Você também não deve usar GetHashCode para testar se duas cadeias de caracteres representam referências de objeto iguais, porque a cadeia de caracteres está internada. Para testar o encadeamento de strings, chame o método String.IsInterned.

Os métodos Object.GetHashCode e RuntimeHelpers.GetHashCode diferem da seguinte maneira:

  • Object.GetHashCode retorna um código hash baseado na definição de igualdade do objeto. Por exemplo, duas cadeias de caracteres com conteúdo idêntico retornarão o mesmo valor para Object.GetHashCode.
  • RuntimeHelpers.GetHashCode retorna um código hash que indica a identidade do objeto. Ou seja, duas variáveis de cadeia de caracteres cujo conteúdo é idêntico e que representam uma cadeia de caracteres internada (consulte a seção Internação de Cadeia de Caracteres ) ou que representam uma única cadeia de caracteres na memória retornam códigos hash idênticos.

Importante

Observe que GetHashCode sempre retorna códigos de hash idênticos para referências de objeto iguais. No entanto, o inverso não é verdadeiro: códigos de hash iguais não indicam referências de objeto iguais. Um valor de código hash específico não é exclusivo para uma referência de objeto específica; diferentes referências de objeto podem gerar códigos de hash idênticos.

Esse método é usado por compiladores.

Centralização de cadeia de caracteres

O CLR (Common Language Runtime) mantém um pool interno de cadeias de caracteres e armazena literais no pool. Se duas cadeias de caracteres (por exemplo, str1 e str2) forem formadas a partir de um literal de cadeia de caracteres idêntico, o CLR definirá str1 e str2 para apontarem para o mesmo local no heap gerenciado para conservar a memória. Chamar RuntimeHelpers.GetHashCode nesses dois objetos string produzirá o mesmo código hash, ao contrário do segundo item listado na seção anterior.

O CLR adiciona somente literais ao pool. Os resultados de operações de cadeia de caracteres, como concatenação, não são adicionados ao pool, a menos que o compilador resolva a concatenação da cadeia de caracteres como um único literal de cadeia de caracteres. Portanto, se str2 foi criado como resultado de uma operação de concatenação e str2 é idêntico a str1, o uso RuntimeHelpers.GetHashCode nesses dois objetos de cadeia de caracteres não produzirá o mesmo código hash.

Se você quiser adicionar uma cadeia de caracteres concatenada ao pool explicitamente, use o String.Intern método.

Você também pode usar o String.IsInterned método para verificar se uma cadeia de caracteres tem uma referência interna.

Exemplos

O exemplo a seguir demonstra a diferença entre os métodos Object.GetHashCode e RuntimeHelpers.GetHashCode. A saída do exemplo ilustra o seguinte:

  • Ambos os conjuntos de códigos de hash para o primeiro conjunto de cadeias de caracteres passadas para o ShowHashCodes método são diferentes, pois as cadeias de caracteres são completamente diferentes.

  • Object.GetHashCode gera o mesmo código hash para o segundo conjunto de cadeias de caracteres passadas para o ShowHashCodes método, pois as cadeias de caracteres são iguais. No entanto, o método RuntimeHelpers.GetHashCode não faz. A primeira cadeia de caracteres é definida usando um literal de cadeia de caracteres e, portanto, é armazenada de forma interna. Embora o valor da segunda cadeia de caracteres seja o mesmo, ele não é interno, pois é retornado por uma chamada para o String.Format método.

  • No caso da terceira cadeia de caracteres, os códigos de hash produzidos por Object.GetHashCode para ambas as cadeias de caracteres são idênticos assim como os códigos de hash produzidos por RuntimeHelpers.GetHashCode. Isso ocorre porque o compilador tratou o valor atribuído a ambas as cadeias de caracteres como um literal de cadeia de caracteres única e, portanto, as variáveis de cadeia de caracteres referem-se à mesma cadeia de caracteres internada.

using System;
using System.Runtime.CompilerServices;

public class Example
{
   public static void Main()
   {
      Console.WriteLine("{0,-18} {1,6} {2,18:N0}    {3,6} {4,18:N0}\n",
                        "", "Var 1", "Hash Code", "Var 2", "Hash Code");
      
      // Get hash codes of two different strings.
      String sc1 = "String #1";
      String sc2 = "String #2";
      ShowHashCodes("sc1", sc1, "sc2", sc2);
 
      // Get hash codes of two identical non-interned strings.
      String s1 = "This string";
      String s2 = String.Format("{0} {1}", "This", "string");
      ShowHashCodes("s1", s1, "s2", s2);

      // Get hash codes of two (evidently concatenated) strings.
      String si1 = "This is a string!";
      String si2 = "This " + "is " + "a " + "string!";
      ShowHashCodes("si1", si1, "si2", si2);
   }

   private static void ShowHashCodes(String var1, Object value1, 
                                     String var2, Object value2)
   {
      Console.WriteLine("{0,-18} {1,6} {2,18:X8}    {3,6} {4,18:X8}",
                        "Obj.GetHashCode", var1, value1.GetHashCode(),
                        var2, value2.GetHashCode());

      Console.WriteLine("{0,-18} {1,6} {2,18:X8}    {3,6} {4,18:X8}\n",
                        "RTH.GetHashCode", var1, RuntimeHelpers.GetHashCode(value1),
                        var2, RuntimeHelpers.GetHashCode(value2));
   }
}
// The example displays output similar to the following:
//                        Var 1          Hash Code     Var 2          Hash Code
//    
//    Obj.GetHashCode       sc1           94EABD27       sc2           94EABD24
//    RTH.GetHashCode       sc1           02BF8098       sc2           00BB8560
//    
//    Obj.GetHashCode        s1           29C5A397        s2           29C5A397
//    RTH.GetHashCode        s1           0297B065        s2           03553390
//    
//    Obj.GetHashCode       si1           941BCEA5       si2           941BCEA5
//    RTH.GetHashCode       si1           01FED012       si2           01FED012
Imports System.Runtime.CompilerServices

Module Example
   Public Sub Main()
      Console.WriteLine("{0,-18} {1,6} {2,18:N0}    {3,6} {4,18:N0}",
                        "", "Var 1", "Hash Code", "Var 2", "Hash Code")
      Console.WriteLine()
      
      ' Get hash codes of two different strings.
      Dim sc1 As String = "String #1"
      Dim sc2 As String = "String #2"
      ShowHashCodes("sc1", sc1, "sc2", sc2)
 
      ' Get hash codes of two identical non-interned strings.
      Dim s1 As String = "This string"
      Dim s2 As String = String.Format("{0} {1}", "This", "string")
      ShowHashCodes("s1", s1, "s2", s2)

      ' Get hash codes of two (evidently concatenated) strings.
      Dim si1 As String = "This is a string!"
      Dim si2 As String = "This " + "is " + "a " + "string!"
      ShowHashCodes("si1", si1, "si2", si2)
   End Sub
   
   Private Sub ShowHashCodes(var1 As String, value1 As Object, 
                             var2 As String, value2 As Object)
      Console.WriteLine("{0,-18} {1,6} {2,18:X8}    {3,6} {4,18:X8}",
                        "Obj.GetHashCode", var1, value1.GetHashCode,
                        var2, value2.GetHashCode)

      Console.WriteLine("{0,-18} {1,6} {2,18:X8}    {3,6} {4,18:X8}",
                        "RTH.GetHashCode", var1, RuntimeHelpers.GetHashCode(value1),
                        var2, RuntimeHelpers.GetHashCode(value2))
      Console.WriteLine()
   End Sub
End Module
' The example displays output similar to the following:
'                        Var 1          Hash Code     Var 2          Hash Code
'    
'    Obj.GetHashCode       sc1           94EABD27       sc2           94EABD24
'    RTH.GetHashCode       sc1           02BF8098       sc2           00BB8560
'    
'    Obj.GetHashCode        s1           29C5A397        s2           29C5A397
'    RTH.GetHashCode        s1           0297B065        s2           03553390
'    
'    Obj.GetHashCode       si1           941BCEA5       si2           941BCEA5
'    RTH.GetHashCode       si1           01FED012       si2           01FED012