Condividi tramite


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