共用方式為


System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode 方法

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

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

警告

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

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

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

這很重要

請注意, GetHashCode 一律會針對相等對象參考傳回相同的哈希碼。 不過,反之情況未必成立:相等的哈希碼不代表相等的對象參考。 特定哈希碼值對特定對象參考而言並不是唯一的;不同的對象參考可以產生相同的哈希碼。

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

字串插入

Common Language Runtime (CLR) 會維護字串的內部集區,並將常值儲存在集區中。 如果兩個字串(例如 str1str2)是從相同的字串常值形成,則 CLR 會設定 str1str2 指向 Managed 堆積上的相同位置,以節省記憶體。 呼叫 RuntimeHelpers.GetHashCode 這兩個字串對象會產生相同的雜湊碼,這與上一節中的第二項不一致。

CLR 僅將文字常數新增至集區。 除非編譯器將串接的結果解析為單一字串字面值,否則不會將如串接等字串操作的結果加入到常值池中。 因此,如果 str2 建立為串連作業的結果,且 str2str1相同,則在這 RuntimeHelpers.GetHashCode 兩個字串物件上使用 時,不會產生相同的哈希程序代碼。

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

您也可以使用 String.IsInterned 方法來檢查字串是否有內部化的參考。

範例

下列範例示範 Object.GetHashCodeRuntimeHelpers.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