Método System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode

En este artículo se proporcionan comentarios adicionales a la documentación de referencia de esta API.

El RuntimeHelpers.GetHashCode método siempre llama al Object.GetHashCode método de forma no virtual, incluso si el tipo del objeto ha invalidado el Object.GetHashCode método . Por lo tanto, el uso RuntimeHelpers.GetHashCode de puede diferir de llamar GetHashCode directamente al objeto con el Object.GetHashCode método .

Advertencia

Aunque el RuntimeHelpers.GetHashCode método devuelve códigos hash idénticos para referencias de objeto idénticas, no debe usar este método para probar la identidad del objeto, ya que este código hash no identifica de forma única una referencia de objeto. Para probar la identidad de objeto (es decir, para probar que dos objetos hacen referencia al mismo objeto en memoria), llame al Object.ReferenceEquals método . Tampoco debe usar GetHashCode para probar si dos cadenas representan referencias de objeto iguales, ya que la cadena está internada. Para probar la internación de cadenas, llame al String.IsInterned método .

Los Object.GetHashCode métodos y RuntimeHelpers.GetHashCode difieren de la siguiente manera:

  • Object.GetHashCode devuelve un código hash basado en la definición de igualdad del objeto. Por ejemplo, dos cadenas con contenido idéntico devolverán el mismo valor para Object.GetHashCode.
  • RuntimeHelpers.GetHashCode devuelve un código hash que indica la identidad del objeto. Es decir, dos variables de cadena cuyo contenido es idéntico y que representan una cadena internada (vea la sección Interning de cadenas) o que representan una sola cadena en la memoria devuelven códigos hash idénticos.

Importante

Tenga en cuenta que GetHashCode siempre devuelve códigos hash idénticos para las referencias de objeto iguales. Sin embargo, la inversa no es true: los códigos hash iguales no indican referencias de objeto iguales. Un valor de código hash determinado no es único para una referencia de objeto determinada; diferentes referencias de objeto pueden generar códigos hash idénticos.

Los compiladores usan este método.

Interning de cadenas

Common Language Runtime (CLR) mantiene un grupo interno de cadenas y almacena literales en el grupo. Si dos cadenas (por ejemplo, str1 y str2) se forman a partir de un literal de cadena idéntico, CLR establecerá str1 y str2 apuntará a la misma ubicación en el montón administrado para conservar la memoria. Al llamar RuntimeHelpers.GetHashCode a en estos dos objetos de cadena, se producirá el mismo código hash, contrario al segundo elemento con viñetas de la sección anterior.

CLR agrega solo literales al grupo. Los resultados de las operaciones de cadena, como la concatenación, no se agregan al grupo, a menos que el compilador resuelva la concatenación de cadena como un literal de cadena único. Por lo tanto, si str2 se creó como resultado de una operación de concatenación y str2 es idéntica a str1, el uso RuntimeHelpers.GetHashCode de en estos dos objetos de cadena no generará el mismo código hash.

Si desea agregar una cadena concatenada al grupo explícitamente, use el String.Intern método .

También puede usar el String.IsInterned método para comprobar si una cadena tiene una referencia interna.

Ejemplos

En el ejemplo siguiente se muestra la diferencia entre los Object.GetHashCode métodos y RuntimeHelpers.GetHashCode . La salida del ejemplo muestra lo siguiente:

  • Ambos conjuntos de códigos hash para el primer conjunto de cadenas que se pasan al ShowHashCodes método son diferentes, ya que las cadenas son completamente diferentes.

  • Object.GetHashCode genera el mismo código hash para el segundo conjunto de cadenas que se pasan al ShowHashCodes método , ya que las cadenas son iguales. Sin embargo, el RuntimeHelpers.GetHashCode método no lo hace. La primera cadena se define mediante un literal de cadena y, por tanto, se interna. Aunque el valor de la segunda cadena es el mismo, no está internado, porque se devuelve mediante una llamada al String.Format método .

  • En el caso de la tercera cadena, los códigos hash generados por Object.GetHashCode para ambas cadenas son idénticos, como son los códigos hash generados por RuntimeHelpers.GetHashCode. Esto se debe a que el compilador ha tratado el valor asignado a ambas cadenas como un literal de cadena único, por lo que las variables de cadena hacen referencia a la misma cadena internada.

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