Udostępnij za pośrednictwem


System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode metoda

Ten artykuł zawiera dodatkowe uwagi dotyczące dokumentacji referencyjnej dla tego interfejsu API.

Metoda RuntimeHelpers.GetHashCode zawsze wywołuje metodę Object.GetHashCode nie wirtualnie, nawet jeśli typ obiektu nadpisze metodę Object.GetHashCode. W związku z tym użycie RuntimeHelpers.GetHashCode może różnić się od wywoływania GetHashCode bezpośrednio na obiekcie za pomocą metody Object.GetHashCode.

Ostrzeżenie

RuntimeHelpers.GetHashCode Mimo że metoda zwraca identyczne kody skrótów dla identycznych odwołań do obiektów, nie należy używać tej metody do testowania tożsamości obiektu, ponieważ ten kod skrótu nie identyfikuje unikatowo odwołania do obiektu. Aby przetestować tożsamość obiektu (czyli przetestować, że dwa obiekty odwołują się do tego samego obiektu w pamięci), wywołaj metodę Object.ReferenceEquals . Nie należy też używać GetHashCode do testowania, czy dwa ciągi reprezentują referencje do tego samego obiektu, ponieważ ciąg jest przechowywany wewnętrznie. Aby przetestować wstawianie łańcuchów, wywołaj metodę String.IsInterned.

Metody Object.GetHashCode i RuntimeHelpers.GetHashCode różnią się w następujący sposób:

  • Object.GetHashCode Zwraca kod skrótu oparty na definicji równości obiektu. Na przykład dwa ciągi o identycznej zawartości będą zwracać tę samą wartość dla elementu Object.GetHashCode.
  • RuntimeHelpers.GetHashCode Zwraca kod skrótu wskazujący tożsamość obiektu. Oznacza to, że dwie zmienne ciągu, których zawartość jest identyczna i które reprezentują ciąg, który jest internowany (zobacz sekcję Internowanie ciągów) lub reprezentują jeden ciąg w pamięci, zwracają identyczne kody skrótu.

Ważne

Należy pamiętać, że GetHashCode zawsze zwraca identyczne kody skrótów dla odwołań do równego obiektu. Jednakże, odwrotna sytuacja nie jest prawdziwa: równe kody skrótów nie wskazują na to, że odwołania do obiektów są równe. Określona wartość kodu skrótu nie jest unikatowa dla określonego odwołania do obiektu; różne odwołania do obiektów mogą generować identyczne kody skrótów.

Ta metoda jest używana przez kompilatory.

Internowanie łańcuchów

Środowisko uruchomieniowe języka wspólnego (CLR) utrzymuje wewnętrzną pulę ciągów znakowych i przechowuje w niej literały. Jeśli dwa ciągi (na przykład str1 i str2) są tworzone na podstawie identycznego literału ciągu, CLR ustawi str1 i str2, aby wskazywały na tę samą lokalizację na zarządzanej stercie w celu zaoszczędzenia pamięci. Wywołanie RuntimeHelpers.GetHashCode tych dwóch obiektów ciągów spowoduje wygenerowanie tego samego kodu skrótu, w przeciwieństwie do drugiego elementu punktowanego w poprzedniej sekcji.

CLR dodaje tylko literały do tej puli. Wyniki operacji ciągów, takich jak łączenie, nie są dodawane do puli, chyba że kompilator rozpozna łączenie ciągów jako literał pojedynczego ciągu. W związku z tym, jeśli str2 został utworzony w wyniku operacji łączenia, a str2 jest identyczny z str1, użycie RuntimeHelpers.GetHashCode na tych dwóch obiektach tekstowych nie spowoduje wygenerowania tego samego kodu skrótu.

Jeśli chcesz jawnie dodać połączony ciąg do puli, użyj String.Intern metody .

Możesz również użyć metody String.IsInterned, aby sprawdzić, czy ciąg ma odniesienie do internowania.

Przykłady

W poniższym przykładzie pokazano różnicę między metodami Object.GetHashCode i RuntimeHelpers.GetHashCode . Dane wyjściowe z przykładu ilustrują następujące dane:

  • Oba zestawy kodów skrótów dla pierwszego zestawu ciągów przekazanych do ShowHashCodes metody są różne, ponieważ ciągi są zupełnie inne.

  • Object.GetHashCode Generuje ten sam kod skrótu dla drugiego zestawu ciągów przekazanych do ShowHashCodes metody, ponieważ ciągi są równe. Jednak metoda RuntimeHelpers.GetHashCode nie działa. Pierwszy ciąg jest definiowany przy użyciu literału ciągu i dlatego jest internowany. Chociaż wartość drugiego ciągu jest taka sama, nie jest internowana, ponieważ jest zwracana przez wywołanie String.Format metody .

  • W przypadku trzeciego ciągu kody skrótów generowane przez Object.GetHashCode dla obu ciągów są identyczne, podobnie jak kody skrótów generowane przez RuntimeHelpers.GetHashCode na ich rzecz. Dzieje się tak, ponieważ kompilator potraktował wartość przypisaną do obu ciągów jako literał pojedynczego ciągu, a więc zmienne ciągu odwołują się do tego samego ciągu internowanego.

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