Метод 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