Exportar (0) Imprimir
Expandir todo
Este artículo proviene de un motor de traducción automática. Mueva el puntero sobre las frases del artículo para ver el texto original. Más información.
Traducción
Original

Object.GetHashCode (Método)

Sirve como una función hash para un tipo en particular.

Espacio de nombres:  System
Ensamblado:  mscorlib (en mscorlib.dll)

public virtual int GetHashCode()

Valor devuelto

Tipo: System.Int32
Código hash para el objeto actual.

Un código hash es un valor numérico que se utiliza para insertar y para identificar un objeto en una colección hash- basada como la clase de Dictionary<TKey, TValue> , la clase de Hashtable , o un tipo derivado de la clase de DictionaryBase . El método de GetHashCode proporciona este código hash para los algoritmos que necesitan comprobaciones rápidas de igualdad del objeto.

NotaNota

Para obtener información sobre cómo los códigos hash se utilizan en tablas hash y para algunos algoritmos adicionales del código hash, vea Función hash la entrada en Wikipedia.

La implementación por defecto del método GetHashCode no garantiza la devolución de valores únicos para distintos objetos. Sin embargo, el inverso no es cierta: los códigos hash iguales no implican igualdad de objeto, porque los objetos (desiguales) pueden tener códigos hash idénticos. Además, .NET Framework no garantiza la implementación predeterminada del método de GetHashCode , y el valor que este método devuelva puede diferir entre las versiones de .NET Framework y las plataformas, como plataformas de 32 bits y 64 bits. Por estas razones, no utilice la implementación predeterminada de este método como identificador de objeto único para algoritmos hash propósitos. Dos consecuencias siguen de esto:

  • No debe suponer que los códigos hash de igual implican igualdad del objeto.

  • Nunca debería guardar o utilizar un código hash fuera del dominio de aplicación en el que se creó, porque puede el mismo objeto hash en dominios de aplicación, procesos, y plataformas.

Nota de precauciónPrecaución

Un código hash está pensado para la inserción y la búsqueda eficaces en las colecciones basadas en una tabla hash. Un código hash no es un valor permanente. Por este motivo:

  • No serialice los valores de código hash ni almacénelos en bases de datos.

  • No utilice el código hash como clave para recuperar un objeto de colección con clave.

  • No envíe los códigos hash entre dominios de aplicación o de procesos. En algunos casos, los códigos hash se pueden calcular de dominio de por- proceso o la por- aplicación.

  • No utilice el código hash en lugar de un valor devuelto por una función criptográfica de hash si necesita un hash criptográficamente segura. Para los valores hash criptográficos, utilice una clase derivada de la clase de System.Security.Cryptography.HashAlgorithm o de System.Security.Cryptography.KeyedHashAlgorithm .

  • No pruebe la igualdad de códigos hash para determinar si dos objetos son iguales. (Los objetos distintos pueden tener códigos hash idénticos). Para comprobar la igualdad, llame al método de ReferenceEquals o de Equals .

El método GetHashCode puede ser reemplazado por un tipo derivado. Si GetHashCode no se reemplaza, los códigos hash para los tipos de referencia son calculados llamando al método de Object.GetHashCode de la clase base, que calcula un código hash basado en la referencia de un objeto; para obtener más información, vea RuntimeHelpers.GetHashCode. Es decir dos objetos para los que el método de ReferenceEquals devuelve true tienen códigos hash idénticos. Si los tipos de valor no invalidan GetHashCode, el método de ValueType.GetHashCode de la clase base utiliza la reflexión para calcular el código hash según los valores de los campos del tipo. Es decir tipos de valor cuyos campos tienen valores iguales tener códigos hash iguales. Para obtener más información sobre cómo invalidar GetHashCode, vea la sección “notas a los herederos”.

Nota de precauciónPrecaución

Si reemplaza el método de GetHashCode , también debe reemplazar Equals, y viceversa. Si el método invalidado de Equals devuelve true cuando dos objetos se comprueban la igualdad, el método reemplazado de GetHashCode debe devolver el mismo valor para los dos objetos.

Si un objeto que se usa como una clave en una tabla hash no proporciona una implementación útil de GetHashCode, puede especificar un proveedor de código hash proporcionando una implementación de IEqualityComparer a una de las sobrecargas del constructor de clase de Hashtable .

Notas para Windows en tiempo de ejecución

Cuando se llama al método de GetHashCode en una clase de Windows en tiempo de ejecución, proporciona el comportamiento predeterminado para las clases que no reemplazan GetHashCode. Esto forma parte de la compatibilidad que .NET Framework proporciona para Windows en tiempo de ejecución (vea Compatibilidad de .NET Framework con las aplicaciones de la Tienda Windows y Windows en tiempo de ejecución). Las clases de Windows en tiempo de ejecución no heredan Object, y no implementan actualmente GetHashCode. Sin embargo, aparecen para tener ToString, Equals(Object), y métodos de GetHashCode cuando se utiliza en código de C# o Visual Basic, y .NET Framework proporciona el comportamiento predeterminado para estos métodos.

NotaNota

las clases deWindows en tiempo de ejecución programadas en C# o Visual Basic pueden invalidar el método de GetHashCode .

Notas para los herederos

Una función hash se utiliza para generar con rapidez un número (código hash) que se corresponda con el valor de un objeto. Las funciones hash normalmente son específicas de cada tipo y, de unicidad, deben utilizar al menos uno de los campos de instancia como entrada. Los códigos hash no se deben calcular mediante los valores de campos estáticos.

Para las clases derivadas de Object, el método de GetHashCode puede delegar a Object.GetHashCode() de la clase base la implementación sólo si la clase derivada define igualdad para ser igualdad de referencia. La implementación predeterminada de GetHashCode para los tipos de referencia devuelve un código hash que es equivalente a que es devuelto por el método de RuntimeHelpers.GetHashCode(Object) . Puede reemplazar GetHashCode para los tipos de referencia inmutables. Normalmente para los tipos de referencia mutables, debe invalidar GetHashCode sólo si:

  • Puede calcular el código hash de los campos que no son mutables; o

  • Puede asegurarse de que el código hash de un objeto mutable no cambie mientras que el objeto está contenido en una colección que confíe en el código hash.

Si no, crea que el objeto mutable se perderá en la tabla hash. Si elige reemplazar GetHashCode para un tipo de referencia mutable, la documentación debe indicar que los usuarios de tipo no deben modificar los valores del objeto como el objeto se almacena en una tabla hash.

Para los tipos de valor, ValueType.GetHashCode proporciona una aplicación de código hash predeterminada que utiliza la reflexión. Debería considerar invalidarla para mejorar el rendimiento.

NotaNota

Para obtener más información y ejemplos que calculan códigos hash de diversas maneras, vea la sección de ejemplos.

Una función hash debe tener las siguientes propiedades:

  • Si dos objetos resultan iguales al compararlos, el método GetHashCode para cada objeto debe devolver el mismo valor. Sin embargo, si dos objetos no se consideran iguales, los métodos de GetHashCode para los dos objetos no tienen que devolver varios valores.

  • El método GetHashCode para un objeto debe devolver de forma consecuente el mismo código hash mientras no haya ninguna modificación en el estado del objeto que determine el valor devuelto del método Equals del objeto. Observe que esto sólo es cierto para la ejecución actual de una aplicación, y que se puede devolver un código hash diferente si la aplicación se ejecuta de nuevo.

  • Para obtener el máximo rendimiento, una función hash debe generar una distribución uniforme para toda la entrada, incluida la entrada que se agrupa mucho. Una consecuencia es que las pequeñas modificaciones en el estado de objeto deben provocar modificaciones grandes al código hash resultante para mejorar el rendimiento de la tabla hash.

  • Las funciones hash deben ser baratas calcular.

  • El método de GetHashCode no debería producir excepciones.

Por ejemplo, la implementación del método GetHashCode proporcionada por la clase String devuelve códigos hash idénticos para valores de cadena idénticos. Por ello, dos objetos String devuelven el mismo código hash si representan el mismo valor de cadena. Asimismo, el método utiliza todos los caracteres de la cadena para generar una salida con una distribución aleatoria razonable, incluso en el caso de que la entrada esté agrupada en ciertos intervalos (por ejemplo, es posible que varios usuarios tengan cadenas que contengan únicamente los 128 caracteres ASCII inferiores, aunque una cadena puede contener cualquiera de los 65.535 caracteres Unicode).

El hecho de proporcionar una función hash adecuada a una clase puede influir de forma significativa en el rendimiento a la hora de agregar dichos objetos a una tabla hash. En una tabla hash con claves que proporcionan una buena implementación de una función hash, buscando un elemento requiere tiempo constante (por ejemplo, un O (1) operación). En una tabla hash con una implementación inadecuada de una función hash, el rendimiento de una búsqueda depende del número de elementos de la tabla hash (por ejemplo, una operación O(n), donde n es el número de elementos de la tabla hash). Un usuario malintencionado puede los datos de entrada que aumenta el número de conflictos, que pueden degradar significativamente el rendimiento de las aplicaciones que dependen de las tablas hash, en las condiciones siguientes:

  • Cuando las funciones hash generan conflictos frecuentes.

  • Cuando una proporción grande de objetos en los códigos hash de la producción de tabla hash que son iguales o aproximadamente igual a otro.

  • Cuando los usuarios entran datos que se calcula el código hash.

Las clases derivadas que reemplazan el método GetHashCode también deben reemplazar el método Equals para garantizar que dos objetos considerados iguales tengan el mismo código hash; en caso contrario, puede que el tipo Hashtable no funcione correctamente.

Una de las maneras más simples de calcular un código hash para un valor numérico que tiene el mismo o un intervalo menor que el tipo de Int32 es devolver simplemente ese valor. El ejemplo siguiente se muestra una implementación de una estructura de Number .


using System;

public struct Number
{
   private int n;

   public Number(int value)
   {
      n = value;
   }

   public int Value
   {
      get { return n; }
   }

   public override bool Equals(Object obj)
   {
      if (obj == null || ! (obj is Number)) 
         return false;
      else
         return n == ((Number) obj).n;
   }      

   public override int GetHashCode()
   {
      return n;
   }

   public override string ToString()
   {
      return n.ToString();
   }
}

public class Example
{
   public static void Main()
   {
      Random rnd = new Random();
      for (int ctr = 0; ctr <= 9; ctr++) {
         int randomN = rnd.Next(Int32.MinValue, Int32.MaxValue);
         Number n = new Number(randomN);
         Console.WriteLine("n = {0,12}, hash code = {1,12}", n, n.GetHashCode());
      }   
   }
}
// The example displays output like the following:
//       n =   -634398368, hash code =   -634398368
//       n =   2136747730, hash code =   2136747730
//       n =  -1973417279, hash code =  -1973417279
//       n =   1101478715, hash code =   1101478715
//       n =   2078057429, hash code =   2078057429
//       n =   -334489950, hash code =   -334489950
//       n =    -68958230, hash code =    -68958230
//       n =   -379951485, hash code =   -379951485
//       n =    -31553685, hash code =    -31553685
//       n =   2105429592, hash code =   2105429592


En ocasiones, un tipo está formado por varios campos de datos que pueden participar en la generación del código hash. Una manera de generar un código hash es combinar estos campos mediante una operación de XOR (eXclusive OR) , como se muestra en el ejemplo siguiente.


using System;

// A type that represents a 2-D point.
public struct Point
{
    private int x;
    private int y;

    public Point(int x, int y)
    {
       this.x = x;
       this.y = y;
    }

    public override bool Equals(Object obj)
    {
       if (! (obj is Point)) return false;

       Point p = (Point) obj;
       return x == p.x & y == p.y;
    }

    public override int GetHashCode()
    { 
        return x ^ y;
    } 
} 

public class Example
{
   public static void Main()
   {
      Point pt = new Point(5, 8);
      Console.WriteLine(pt.GetHashCode());

      pt = new Point(8, 5);
      Console.WriteLine(pt.GetHashCode());
   }
}
// The example displays the following output:
//       13
//       13


El ejemplo anterior devuelve el mismo código hash para (n1, n2) y (n2, n1), lo que puede producir más conflictos que deseable. Varias soluciones son disponible para que los códigos hash en estos casos no son idénticos. Uno es devolver el código hash de un objeto de Tuple que refleje el orden de cada campo. El ejemplo siguiente se muestra una posible implementación que utilice la clase de Tuple<T1, T2> . Observe, sin embargo, que la sobrecarga de rendimiento de crear instancias de un objeto de Tuple puede afectar significativamente al rendimiento global de una aplicación que almacena un gran número de objetos en tablas hash.


using System;

public struct Point
{
    private int x;
    private int y;

    public Point(int x, int y)
    {
       this.x = x;
       this.y = y;
    }

    public override bool Equals(Object obj)
    {
       if (!(obj is Point)) return false;

       Point p = (Point) obj;
       return x == p.x & y == p.y;
    }

    public override int GetHashCode()
    { 
        return Tuple.Create(x, y).GetHashCode();
    } 
} 

public class Example
{
   public static void Main()
   {
        Point pt = new Point(5, 8);
        Console.WriteLine(pt.GetHashCode());

        pt = new Point(8, 5);
        Console.WriteLine(pt.GetHashCode());
   }
}
// The example displays the following output:
//       173
//       269


Otra solución alternativa implica la carga de los códigos hash individuales por el izquierdo- desplazamiento los códigos hash de campos sucesivos por dos o más bits. Óptimo, en lugar de ser descartada, los bits desplazados fuera más allá de 31 bits deben ajustarse alrededor de en lugar de descartese. Puesto que los bits son descartados por los operadores de izquierdo- MAYÚS en C# y Visual Basic, esto requiere crear un método izquierdo de MAYÚS-y- ajuste como el siguiente:


public int ShiftAndWrap(int value, int positions)
{
    positions = positions & 0x1F;

    // Save the existing bit pattern, but interpret it as an unsigned integer.
    uint number = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
    // Preserve the bits to be discarded.
    uint wrapped = number >> (32 - positions);
    // Shift and wrap the discarded bits.
    return BitConverter.ToInt32(BitConverter.GetBytes((number << positions) | wrapped), 0);
}


El siguiente ejemplo se utiliza este método de MAYÚS-y- ajuste para calcular el código hash de la estructura de Point utilizada en los ejemplos anteriores.


using System;

public struct Point
{
    private int x;
    private int y;

    public Point(int x, int y)
    {
       this.x = x;
       this.y = y;
    }

    public override bool Equals(Object obj)
    {
       if (!(obj is Point)) return false;

       Point p = (Point) obj;
       return x == p.x & y == p.y;
    }

    public override int GetHashCode()
    { 
        return ShiftAndWrap(x.GetHashCode(), 2) ^ y.GetHashCode();
    } 

    private int ShiftAndWrap(int value, int positions)
    {
        positions = positions & 0x1F;

        // Save the existing bit pattern, but interpret it as an unsigned integer.
        uint number = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
        // Preserve the bits to be discarded.
        uint wrapped = number >> (32 - positions);
        // Shift and wrap the discarded bits.
        return BitConverter.ToInt32(BitConverter.GetBytes((number << positions) | wrapped), 0);
    }
} 

public class Example
{
   public static void Main()
   {
        Point pt = new Point(5, 8);
        Console.WriteLine(pt.GetHashCode());

        pt = new Point(8, 5);
        Console.WriteLine(pt.GetHashCode());
   }
}
// The example displays the following output:
//       28
//       37 


.NET Framework

Compatible con: 4.5.2, 4.5.1, 4.5, 4, 3.5, 3.0, 2.0, 1.1, 1.0

.NET Framework Client Profile

Compatible con: 4, 3.5 SP1

Biblioteca de clases portable

Compatible con: Biblioteca de clases portable

.NET para aplicaciones de la Tienda Windows

Compatible con: Windows 8

.NET para aplicaciones de Windows Phone

Compatible con: Windows Phone 8, Silverlight 8.1

Windows Phone 8.1, Windows Phone 8, Windows 8.1, Windows Server 2012 R2, Windows 8, Windows Server 2012, Windows 7, Windows Vista SP2, Windows Server 2008 (no se admite el rol Server Core), Windows Server 2008 R2 (se admite el rol Server Core con SP1 o versiones posteriores; no se admite Itanium)

.NET Framework no admite todas las versiones de todas las plataformas. Para obtener una lista de las versiones compatibles, vea Requisitos de sistema de .NET Framework.

Adiciones de comunidad

AGREGAR
Mostrar:
© 2014 Microsoft