语言

RuntimeHelpers.GetHashCode(Object) 方法

定义

用作特定对象的哈希函数,适用于使用哈希代码(如哈希表)的算法和数据结构。

public:
 static int GetHashCode(System::Object ^ o);
public static int GetHashCode(object o);
public static int GetHashCode(object? o);
static member GetHashCode : obj -> int
Public Shared Function GetHashCode (o As Object) As Integer

参数

o
Object

要为其检索哈希代码的对象。

返回

由参数标识 o 的对象哈希代码。

示例

以下示例演示了 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

注解

RuntimeHelpers.GetHashCode 方法始终以非虚拟方式调用 Object.GetHashCode 方法,即使对象的类型已重写 Object.GetHashCode 方法。 因此,使用 RuntimeHelpers.GetHashCode 可能与使用 GetHashCode 方法直接在对象上调用 Object.GetHashCode 不同。

Warning

RuntimeHelpers.GetHashCode尽管该方法为相同的对象引用返回相同的哈希代码,但不应使用此方法测试对象标识,因为此哈希代码不会唯一标识对象引用。 若要测试对象标识(即测试两个对象在内存中引用同一对象),请调用该方法 Object.ReferenceEquals 。 也不应该使用 GetHashCode 来测试两个字符串是否代表相等的对象引用,因为该字符串是驻留的。 若要测试字符串驻留,请调用String.IsInterned方法。

Object.GetHashCode方法与RuntimeHelpers.GetHashCode方法的区别如下:

  • Object.GetHashCode 返回一个哈希代码,该代码基于对象的相等性定义。 例如,包含相同内容的两个字符串将返回相同的值 Object.GetHashCode。
  • RuntimeHelpers.GetHashCode 返回指示对象标识的哈希代码。 也就是说,两个字符串变量的内容相同,而且表示一个驻留的字符串(请参阅 字符串驻留 部分)或表示内存中的单个字符串时,它们将返回相同的哈希代码。

Important

请注意, GetHashCode 始终返回相同对象引用的相同哈希代码。 但是,反向不是真的:相等哈希代码不指示相等的对象引用。 特定哈希代码值对特定对象引用不是唯一的;不同的对象引用可以生成相同的哈希代码。

编译器使用此方法。

字符串驻留

公共语言运行时(CLR)维护一个字符串的内部池,并将字面值存储在该池中。 如果两个字符串(例如 str1 ,和 str2)是从相同的字符串文本构成的,则 CLR 将设置 str1 并 str2 指向托管堆上的同一位置以节省内存。 调用这两个字符串对象上的 RuntimeHelpers.GetHashCode 将生成相同的哈希值,这与上一部分中的第二个项目符号项相反。

CLR 仅将文本添加到池中。 除非编译器将字符串连接解析为单个字符串字面量,否则连接等字符串操作的结果不会被添加到池中。 因此,如果 str2 是串联操作的结果,并且 str2 与 str1 相同,那么在这两个字符串对象上使用 RuntimeHelpers.GetHashCode 将不会产生相同的哈希代码。

如果要显式向池添加串联字符串,请使用 String.Intern 该方法。

还可以使用 String.IsInterned 方法来检查字符串是否具有驻留引用。

适用于

另请参阅