Metodo System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode
Questo articolo fornisce osservazioni supplementari alla documentazione di riferimento per questa API.
Il RuntimeHelpers.GetHashCode metodo chiama sempre il Object.GetHashCode metodo non virtualmente, anche se il tipo dell'oggetto ha eseguito l'override del Object.GetHashCode metodo. Pertanto, l'uso RuntimeHelpers.GetHashCode di può differire dalla chiamata GetHashCode
direttamente sull'oggetto con il Object.GetHashCode metodo .
Avviso
Anche se il RuntimeHelpers.GetHashCode metodo restituisce codici hash identici per riferimenti a oggetti identici, non è consigliabile utilizzare questo metodo per verificare l'identità dell'oggetto, perché questo codice hash non identifica in modo univoco un riferimento a un oggetto. Per testare l'identità dell'oggetto, ovvero per verificare che due oggetti facciano riferimento allo stesso oggetto in memoria, chiamare il Object.ReferenceEquals metodo . Né è consigliabile usare GetHashCode per verificare se due stringhe rappresentano riferimenti a oggetti uguali, perché la stringa viene internata. Per verificare l'interno delle stringhe, chiamare il String.IsInterned metodo .
I Object.GetHashCode metodi e RuntimeHelpers.GetHashCode differiscono come segue:
- Object.GetHashCode restituisce un codice hash basato sulla definizione dell'uguaglianza dell'oggetto. Ad esempio, due stringhe con contenuto identico restituiranno lo stesso valore per Object.GetHashCode.
- RuntimeHelpers.GetHashCode restituisce un codice hash che indica l'identità dell'oggetto. Ovvero due variabili stringa il cui contenuto è identico e che rappresentano una stringa internata (vedere la sezione Interning string) o che rappresentano una singola stringa in memoria restituiscono codici hash identici.
Importante
Si noti che GetHashCode restituisce sempre codici hash identici per riferimenti a oggetti uguali. Tuttavia, il contrario non è true: i codici hash uguali non indicano riferimenti a oggetti uguali. Un particolare valore di codice hash non è univoco per un riferimento a un oggetto specifico; riferimenti a oggetti diversi possono generare codici hash identici.
Questo metodo viene usato dai compilatori.
Interning di stringhe
Common Language Runtime (CLR) gestisce un pool interno di stringhe e archivia i valori letterali nel pool. Se due stringhe, ad esempio str1
e str2
, vengono formate da un valore letterale stringa identico, CLR imposta str1
e str2
punta alla stessa posizione nell'heap gestito per risparmiare memoria. La chiamata RuntimeHelpers.GetHashCode a questi due oggetti stringa produrrà lo stesso codice hash, contrariamente al secondo elemento puntato nella sezione precedente.
CLR aggiunge solo valori letterali al pool. I risultati delle operazioni di stringa, ad esempio la concatenazione, non vengono aggiunti al pool, a meno che il compilatore non risolva la concatenazione di stringhe come valore letterale stringa singola. Pertanto, se str2
è stato creato come risultato di un'operazione di concatenazione ed str2
è identico a str1
, l'uso RuntimeHelpers.GetHashCode su questi due oggetti stringa non produrrà lo stesso codice hash.
Se si desidera aggiungere una stringa concatenata al pool in modo esplicito, usare il String.Intern metodo .
È anche possibile utilizzare il String.IsInterned metodo per verificare se una stringa ha un riferimento interno.
Esempi
Nell'esempio seguente viene illustrata la differenza tra i Object.GetHashCode metodi e RuntimeHelpers.GetHashCode . L'output dell'esempio illustra quanto segue:
Entrambi i set di codici hash per il primo set di stringhe passate al
ShowHashCodes
metodo sono diversi, perché le stringhe sono completamente diverse.Object.GetHashCode genera lo stesso codice hash per il secondo set di stringhe passato al
ShowHashCodes
metodo , perché le stringhe sono uguali. Tuttavia, il RuntimeHelpers.GetHashCode metodo non viene usato. La prima stringa viene definita usando un valore letterale stringa e quindi viene internata. Anche se il valore della seconda stringa è lo stesso, non viene internato, perché viene restituito da una chiamata al String.Format metodo .Nel caso della terza stringa, i codici hash prodotti da Object.GetHashCode per entrambe le stringhe sono identici, come sono i codici hash prodotti da RuntimeHelpers.GetHashCode. Questo perché il compilatore ha trattato il valore assegnato a entrambe le stringhe come un singolo valore letterale stringa e quindi le variabili stringa fanno riferimento alla stessa stringa internata.
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