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.GetHashCode和 RuntimeHelpers.GetHashCode 方法不同,如下所示:
- Object.GetHashCode 傳回以物件相等定義為基礎的哈希碼。 例如,兩個具有相同內容的字串會針對 Object.GetHashCode傳回相同的值。
- RuntimeHelpers.GetHashCode 會傳回表示對象識別的哈希碼。 也就是說,兩個字串變數的內容相同,而且代表實習生字串(請參閱 字串插 播區段)或表示記憶體中單一字串串的字串會傳回相同的哈希碼。
重要
請注意, GetHashCode 一律會針對相等對象參考傳回相同的哈希碼。 不過,反向不是 true:相等哈希碼不會指出相等的對象參考。 特定哈希碼值對特定對象參考而言並不是唯一的;不同的對象參考可以產生相同的哈希碼。
編譯程式會使用這個方法。
字串插入
Common Language Runtime (CLR) 會維護字串的內部集區,並將常值儲存在集區中。 如果兩個字串(例如 str1
和 str2
)是從相同的字串常值形成,則 CLR 會設定 str1
並 str2
指向 Managed 堆積上的相同位置,以節省記憶體。 呼叫 RuntimeHelpers.GetHashCode 這兩個字串物件會產生相同的哈希程式代碼,這與上一節中的第二個專案符號專案相反。
CLR 只會將常值新增至集區。 除非編譯程式將字串串連解析為單一字串常值,否則不會將串連之類的字串作業結果新增至集區。 因此,如果 str2
建立為串連作業的結果,且 str2
與 str1
相同,則在這 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