Метод System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode

В этой статье приводятся дополнительные замечания к справочной документации по этому API.

Метод RuntimeHelpers.GetHashCode всегда вызывает метод, отличный Object.GetHashCode от виртуальной, даже если тип объекта переопределяет Object.GetHashCode метод. Поэтому использование RuntimeHelpers.GetHashCode может отличаться от вызова GetHashCode непосредственно в объекте с методом Object.GetHashCode .

Предупреждение

RuntimeHelpers.GetHashCode Хотя метод возвращает идентичные хэш-коды для идентичных ссылок на объекты, этот метод не следует использовать для проверки удостоверения объекта, так как этот хэш-код не однозначно определяет ссылку на объект. Чтобы проверить удостоверение объекта (т. е. для проверки того, что два объекта ссылались на один и тот же объект в памяти), вызовите Object.ReferenceEquals метод. Также не следует проверять GetHashCode , представляют ли две строки равные ссылки на объекты, так как строка интернирована. Чтобы протестировать строковое взаимодействие, вызовите String.IsInterned метод.

Методы Object.GetHashCode отличаются RuntimeHelpers.GetHashCode следующим образом:

  • Object.GetHashCode возвращает хэш-код, основанный на определении равенства объекта. Например, две строки с одинаковым содержимым возвращают одно и то же значение.Object.GetHashCode
  • RuntimeHelpers.GetHashCode возвращает хэш-код, указывающий удостоверение объекта. То есть две строковые переменные, содержимое которых идентично и представляющее строку, которая интернирована (см . раздел "Интернинг строк") или представляющая одну строку в памяти, возвращают идентичные хэш-коды.

Внимание

Обратите внимание, что GetHashCode всегда возвращает одинаковые хэш-коды для ссылок на равные объекты. Однако обратное не верно: равные хэш-коды не указывают равные ссылки на объекты. Определенное хэш-значение кода не является уникальным для конкретной ссылки на объект; разные ссылки на объекты могут создавать одинаковые хэш-коды.

Этот метод используется компиляторами.

Интернинг строк

Среда CLR поддерживает внутренний пул строк и сохраняет литералы в пуле. Если две строки (например, str1 и str2) формируются из идентичного строкового литерала, среда CLR устанавливает str1 и str2 указывает на то же расположение в управляемой куче, чтобы сохранить память. Вызов RuntimeHelpers.GetHashCode этих двух строковых объектов создаст один хэш-код, вопреки второму маркированному элементу в предыдущем разделе.

Среда CLR добавляет только литералы в пул. Результаты строковых операций, таких как объединение, не добавляются в пул, если компилятор не разрешает объединение строк как один строковый литерал. Таким образом, если str2 он был создан в результате операции объединения и str2 идентичен str1использованию этих двух строковых объектов, RuntimeHelpers.GetHashCode он не будет создавать один и тот же хэш-код.

Если вы хотите явно добавить в пул сцепленную строку, используйте String.Intern этот метод.

Метод также можно использовать String.IsInterned для проверка, имеет ли строка интернированную ссылку.

Примеры

В следующем примере показано различие между методами и RuntimeHelpers.GetHashCode методамиObject.GetHashCode. Выходные данные из примера иллюстрируют следующее:

  • Оба набора хэш-кодов для первого набора строк, передаваемых методу ShowHashCodes , отличаются, так как строки совершенно разные.

  • Object.GetHashCode создает тот же хэш-код для второго набора строк, переданных методу ShowHashCodes , так как строки равны. RuntimeHelpers.GetHashCode Однако метод не выполняется. Первая строка определяется с помощью строкового литерала и поэтому интернируется. Хотя значение второй строки совпадает, она не интернирована, так как она возвращается вызовом String.Format метода.

  • В случае третьей строки хэш-коды, созданные для обеих строк, идентичны, как и хэш-коды, созданные Object.GetHashCodeRuntimeHelpers.GetHashCode. Это связано с тем, что компилятор обрабатывает значение, назначенное обеим строкам как один строковый литерал, и поэтому строковые переменные ссылаются на ту же интернированную строку.

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