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

Observação

Este artigo fornece observações complementares à documentação de referência para esta API.

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

Advertência

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, porque 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. 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 internamento de strings, chame o método String.IsInterned.

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

  • 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 que está internada (consulte a seção String Interning ) 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 hash idênticos para referências de objeto iguais. No entanto, o inverso não é verdadeiro: códigos hash iguais não indicam referências de objeto iguais. Um determinado valor de código hash não é exclusivo para uma referência de objeto específica; Diferentes referências de objeto podem gerar códigos hash idênticos.

Este método é usado por compiladores.

Internamento de strings

O ambiente de execução comum (CLR) mantém um conjunto interno de cadeias de caracteres e armazena os literais nesse conjunto. 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 gerido para conservar memória. Ao chamar RuntimeHelpers.GetHashCode nestes dois objetos string, será produzido o mesmo código hash, contrariando o segundo item marcado na seção anterior.

O CLR adiciona apenas 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 de 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 ao str1, usando 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 internada.

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 hash para o primeiro conjunto de cadeias de caracteres passadas para o ShowHashCodes método são diferentes, porque 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, porque as cadeias de caracteres são iguais. No entanto, o método RuntimeHelpers.GetHashCode não. A primeira string é definida usando uma string literal e assim é interpolada. Embora o valor da segunda cadeia de caracteres seja o mesmo, ela não é internada, porque é retornada por uma chamada para o String.Format método.

  • No caso da terceira string, os códigos hash produzidos por Object.GetHashCode para ambas as strings são idênticos, assim como os códigos hash produzidos pela RuntimeHelpers.GetHashCode. Isso ocorre porque o compilador tratou o valor atribuído a ambas as cadeias de caracteres como um único literal de cadeia de caracteres e, portanto, as variáveis de cadeia de caracteres se referem à 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