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次のように異なります。
- Object.GetHashCode は、オブジェクトの等値の定義に基づくハッシュ コードを返します。 たとえば、内容が同じ 2 つの文字列は、同じ値 Object.GetHashCodeを返します。
- RuntimeHelpers.GetHashCode は、オブジェクト ID を示すハッシュ コードを返します。 つまり、内容が同じで、インターンされた文字列を表す 2 つの文字列変数 (「String Interning」セクションを参照 ) またはメモリ内の 1 つの文字列を表す 2 つの文字列変数は、同じハッシュ コードを 返します。
重要
オブジェクト参照が等しい場合は、常に同じハッシュ コードが返されることに GetHashCode 注意してください。 ただし、逆は true ではありません。等しいハッシュ コードは、等しいオブジェクト参照を示しません。 特定のハッシュ コード値は、特定のオブジェクト参照に対して一意ではありません。異なるオブジェクト参照によって同じハッシュ コードが生成される場合があります。
このメソッドはコンパイラによって使用されます。
文字列のインターン
共通言語ランタイム (CLR) メイン文字列の内部プールを格納し、リテラルをプールに格納します。 同一の文字列リテラルから 2 つの文字列 (たとえば、 str1
str2
) が形成されている場合、CLR は設定 str1
され str2
、メモリを節約するためにマネージド ヒープ上の同じ場所を指します。 これら 2 つの文字列オブジェクトを呼び出すと RuntimeHelpers.GetHashCode 、前のセクションの 2 番目の箇条書き項目とは異なり、同じハッシュ コードが生成されます。
CLR は、リテラルのみをプールに追加します。 連結などの文字列操作の結果は、コンパイラが文字列連結を単一の文字列リテラルとして解決しない限り、プールには追加されません。 したがって、連結操作の結果として作成され、同一str1
である場合str2
、str2
これら 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
.NET