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.GetHashCodeRuntimeHelpers.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检查字符串是否具有实习生引用。
示例
以下示例演示了 Object.GetHashCode 方法 RuntimeHelpers.GetHashCode 之间的差异。 该示例的输出演示了以下内容:
传递给
ShowHashCodes
该方法的第一组字符串的两组哈希代码都是不同的,因为字符串完全不同。Object.GetHashCode 为传递给
ShowHashCodes
方法的第二组字符串生成相同的哈希代码,因为字符串相等。 但是,该方法 RuntimeHelpers.GetHashCode 不会。 第一个字符串是使用字符串文本定义的,因此是实习生。 尽管第二个字符串的值相同,但它不是实习生,因为它是由对方法的调用返回的 String.Format 。对于第三个字符串,由 Object.GetHashCode 这两个字符串生成的哈希代码是相同的,与由这两 RuntimeHelpers.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