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 将设置 str1str2 指向托管堆上的同一位置以节省内存。 调用 RuntimeHelpers.GetHashCode 这两个字符串对象将生成相同的哈希代码,这与上一部分中的第二个项目符号项相反。

CLR 仅向池添加文本。 除非编译器将字符串串联解析为单个字符串文本,否则不会将字符串操作(如串联)的结果添加到池中。 因此,如果 str2 创建为串联操作的结果,并且 str2str1在这 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