System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode 方法

本文提供此 API 參考文件的補充備註。

即使RuntimeHelpers.GetHashCode物件的型別已覆寫 Object.GetHashCode 方法,方法一律會以非虛擬方式呼叫 Object.GetHashCode 方法。 因此,使用 RuntimeHelpers.GetHashCode 可能會與使用 Object.GetHashCode 方法直接在 物件上呼叫GetHashCode不同。

警告

RuntimeHelpers.GetHashCode雖然方法會針對相同的對象參考傳回相同的哈希碼,但您不應該使用此方法來測試對象識別,因為這個哈希碼不會唯一識別對象參考。 若要測試對象識別(亦即,若要測試兩個對象參考記憶體中的相同物件),請呼叫 Object.ReferenceEquals 方法。 您也不應該使用 GetHashCode 來測試兩個字串是否代表相等的對象參考,因為字元串是實習生。 若要測試字串插入,請呼叫 String.IsInterned 方法。

Object.GetHashCodeRuntimeHelpers.GetHashCode 方法不同,如下所示:

  • Object.GetHashCode 傳回以物件相等定義為基礎的哈希碼。 例如,兩個具有相同內容的字串會針對 Object.GetHashCode傳回相同的值。
  • RuntimeHelpers.GetHashCode 會傳回表示對象識別的哈希碼。 也就是說,兩個字串變數的內容相同,而且代表實習生字串(請參閱 字串插 播區段)或表示記憶體中單一字串串的字串會傳回相同的哈希碼。

重要

請注意, GetHashCode 一律會針對相等對象參考傳回相同的哈希碼。 不過,反向不是 true:相等哈希碼不會指出相等的對象參考。 特定哈希碼值對特定對象參考而言並不是唯一的;不同的對象參考可以產生相同的哈希碼。

編譯程式會使用這個方法。

字串插入

Common Language Runtime (CLR) 會維護字串的內部集區,並將常值儲存在集區中。 如果兩個字串(例如 str1str2)是從相同的字串常值形成,則 CLR 會設定 str1str2 指向 Managed 堆積上的相同位置,以節省記憶體。 呼叫 RuntimeHelpers.GetHashCode 這兩個字串物件會產生相同的哈希程式代碼,這與上一節中的第二個專案符號專案相反。

CLR 只會將常值新增至集區。 除非編譯程式將字串串連解析為單一字串常值,否則不會將串連之類的字串作業結果新增至集區。 因此,如果 str2 建立為串連作業的結果,且 str2str1相同,則在這 RuntimeHelpers.GetHashCode 兩個字串物件上使用 時,不會產生相同的哈希程序代碼。

如果您想要明確地將串連字串新增至集區,請使用 String.Intern 方法。

您也可以使用 String.IsInterned 方法來檢查字串是否有實習生參考。

範例

下列範例示範 和 RuntimeHelpers.GetHashCode 方法之間的差異Object.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