System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode メソッド

この記事では、この API のリファレンス ドキュメントへの補足的な解説を提供します。

オブジェクトの型がメソッドをObject.GetHashCodeオーバーライドした場合でも、メソッドはRuntimeHelpers.GetHashCode常に非仮想的にメソッドをObject.GetHashCode呼び出します。 そのため、メソッドを使用して RuntimeHelpers.GetHashCode オブジェクトを直接呼び出す GetHashCode のとは Object.GetHashCode 異なる場合があります。

警告

メソッドは RuntimeHelpers.GetHashCode 同じオブジェクト参照に対して同一のハッシュ コードを返しますが、このハッシュ コードはオブジェクト参照を一意に識別しないため、このメソッドを使用してオブジェクト ID をテストしないでください。 オブジェクト ID をテストするには (つまり、2 つのオブジェクトがメモリ内の同じオブジェクトを参照することをテストするために)、メソッドを Object.ReferenceEquals 呼び出します。 また、文字列がインターンされているため、2 つの文字列が等しいオブジェクト参照を表すかどうかをテストするためにも使用 GetHashCode する必要があります。 文字列のインターンをテストするには、メソッドを String.IsInterned 呼び出します。

メソッドとRuntimeHelpers.GetHashCode方法はObject.GetHashCode次のように異なります。

重要

オブジェクト参照が等しい場合は、常に同じハッシュ コードが返されることに GetHashCode 注意してください。 ただし、逆は true ではありません。等しいハッシュ コードは、等しいオブジェクト参照を示しません。 特定のハッシュ コード値は、特定のオブジェクト参照に対して一意ではありません。異なるオブジェクト参照によって同じハッシュ コードが生成される場合があります。

このメソッドはコンパイラによって使用されます。

文字列のインターン

共通言語ランタイム (CLR) メイン文字列の内部プールを格納し、リテラルをプールに格納します。 同一の文字列リテラルから 2 つの文字列 (たとえば、 str1str2) が形成されている場合、CLR は設定 str1 され str2 、メモリを節約するためにマネージド ヒープ上の同じ場所を指します。 これら 2 つの文字列オブジェクトを呼び出すと RuntimeHelpers.GetHashCode 、前のセクションの 2 番目の箇条書き項目とは異なり、同じハッシュ コードが生成されます。

CLR は、リテラルのみをプールに追加します。 連結などの文字列操作の結果は、コンパイラが文字列連結を単一の文字列リテラルとして解決しない限り、プールには追加されません。 したがって、連結操作の結果として作成され、同一str1である場合str2str2これら 2 つの文字列オブジェクトで使用RuntimeHelpers.GetHashCodeしても、同じハッシュ コードは生成されません。

連結された文字列をプールに明示的に追加する場合は、メソッドを使用します String.Intern

このメソッドをString.IsInterned使用して、文字列にインターン参照があるかどうかをチェックすることもできます。

次の例では、メソッドとRuntimeHelpers.GetHashCodeメソッドの違いをObject.GetHashCode示します。 この例からの出力は、次の例を示しています。

  • メソッドに渡される ShowHashCodes 文字列の最初のセットのハッシュ コードのセットは、文字列が完全に異なるため、両方とも異なります。

  • Object.GetHashCode は、文字列が等しいため、メソッドに渡される 2 番目の文字列セットに対して ShowHashCodes 同じハッシュ コードを生成します。 ただし、この RuntimeHelpers.GetHashCode メソッドには対応していません。 最初の文字列は文字列リテラルを使用して定義されるため、強制されます。 2 番目の文字列の値は同じですが、メソッドの呼び出し String.Format によって返されるため、インターンされません。

  • 3 番目の文字列の場合、両方の文字列で Object.GetHashCode 生成されるハッシュ コードは、によって生成される RuntimeHelpers.GetHashCodeハッシュ コードと同じです。 これは、コンパイラが両方の文字列に割り当てられた値を 1 つの文字列リテラルとして扱い、文字列変数が同じインターン文字列を参照するためです。

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