Leer en inglés

Compartir a través de


HashCode Estructura

Definición

Combina el código hash de varios valores en un código hash único.

public struct HashCode
Herencia
HashCode

Ejemplos

Los métodos estáticos de esta clase combinan los códigos hash predeterminados de hasta ocho valores.

using System;
using System.Collections.Generic;

public struct OrderOrderLine : IEquatable<OrderOrderLine>
{
    public int OrderId { get; }
    public int OrderLineId { get; }

    public OrderOrderLine(int orderId, int orderLineId) => (OrderId, OrderLineId) = (orderId, orderLineId);

    public override bool Equals(object obj) => obj is OrderOrderLine o && Equals(o);

    public bool Equals(OrderOrderLine other) => OrderId == other.OrderId && OrderLineId == other.OrderLineId;

    public override int GetHashCode() => HashCode.Combine(OrderId, OrderLineId);
}

class Program
{
    static void Main(string[] args)
    {
        var set = new HashSet<OrderOrderLine>
        {
            new OrderOrderLine(1, 1),
            new OrderOrderLine(1, 1),
            new OrderOrderLine(1, 2)
        };

        Console.WriteLine($"Item count: {set.Count}.");
    }
}
// The example displays the following output:
// Item count: 2.

Importante

ToHashCode() se debe llamar como máximo una vez por instancia de HashCode.

Los métodos de instancia de esta clase combinan los códigos hash de más de ocho valores.

using System;
using System.Collections.Generic;

public struct Path : IEquatable<Path>
{
    public IReadOnlyList<string> Segments { get; }

    public Path(params string[] segments) => Segments = segments;

    public override bool Equals(object obj) => obj is Path o && Equals(o);

    public bool Equals(Path other)
    {
        if (ReferenceEquals(Segments, other.Segments)) return true;
        if (Segments is null || other.Segments is null) return false;
        if (Segments.Count != other.Segments.Count) return false;

        for (var i = 0; i < Segments.Count; i++)
        {
            if (!string.Equals(Segments[i], other.Segments[i]))
                return false;
        }

        return true;
    }

    public override int GetHashCode()
    {
        var hash = new HashCode();

        for (var i = 0; i < Segments?.Count; i++)
            hash.Add(Segments[i]);

        return hash.ToHashCode();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var set = new HashSet<Path>
        {
            new Path("C:", "tmp", "file.txt"),
            new Path("C:", "tmp", "file.txt"),
            new Path("C:", "tmp", "file.tmp")
        };

        Console.WriteLine($"Item count: {set.Count}.");
    }
}
// The example displays the following output:
// Item count: 2.

Los métodos de instancia también combinan los códigos hash generados por una implementación específica IEqualityComparer<T> .

using System;
using System.Collections.Generic;

public struct Path : IEquatable<Path>
{
    public IReadOnlyList<string> Segments { get; }

    public Path(params string[] segments) => Segments = segments;

    public override bool Equals(object obj) => obj is Path o && Equals(o);

    public bool Equals(Path other)
    {
        if (ReferenceEquals(Segments, other.Segments)) return true;
        if (Segments is null || other.Segments is null) return false;
        if (Segments.Count != other.Segments.Count) return false;

        for (var i = 0; i < Segments.Count; i++)
        {
            if (!string.Equals(Segments[i], other.Segments[i], StringComparison.OrdinalIgnoreCase))
                return false;
        }

        return true;
    }

    public override int GetHashCode()
    {
        var hash = new HashCode();

        for (var i = 0; i < Segments?.Count; i++)
            hash.Add(Segments[i], StringComparer.OrdinalIgnoreCase);

        return hash.ToHashCode();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var set = new HashSet<Path>
        {
            new Path("C:", "tmp", "file.txt"),
            new Path("C:", "TMP", "file.txt"),
            new Path("C:", "tmp", "FILE.TXT")
        };

        Console.WriteLine($"Item count: {set.Count}.");
    }
}
// The example displays the following output:
// Item count: 1.

La HashCode estructura debe pasarse por referencia a otros métodos, ya que es un tipo de valor.

using System;
using System.Collections.Generic;

public struct Path : IEquatable<Path>
{
    public IReadOnlyList<string> Segments { get; }

    public Path(params string[] segments) => Segments = segments;

    public override bool Equals(object obj) => obj is Path o && Equals(o);

    public bool Equals(Path other)
    {
        if (ReferenceEquals(Segments, other.Segments)) return true;
        if (Segments is null || other.Segments is null) return false;
        if (Segments.Count != other.Segments.Count) return false;

        for (var i = 0; i < Segments.Count; i++)
        {
            if (!PlatformUtils.PathEquals(Segments[i], other.Segments[i]))
                return false;
        }

        return true;
    }

    public override int GetHashCode()
    {
        var hash = new HashCode();

        for (var i = 0; i < Segments?.Count; i++)
            PlatformUtils.AddPath(ref hash, Segments[i]);

        return hash.ToHashCode();
    }
}

internal static class PlatformUtils
{
    public static bool PathEquals(string a, string b) => string.Equals(a, b, StringComparison.OrdinalIgnoreCase);
    public static void AddPath(ref HashCode hash, string path) => hash.Add(path, StringComparer.OrdinalIgnoreCase);
}

class Program
{
    static void Main(string[] args)
    {
        var set = new HashSet<Path>
        {
            new Path("C:", "tmp", "file.txt"),
            new Path("C:", "TMP", "file.txt"),
            new Path("C:", "tmp", "FILE.TXT")
        };

        Console.WriteLine($"Item count: {set.Count}.");
    }
}
// The example displays the following output:
// Item count: 1.

Comentarios

Puede usar HashCode para combinar varios valores (por ejemplo, campos en una estructura o clase) en un único código hash. Esta estructura tiene métodos estáticos e de instancia que funcionan de forma diferente:

  • Los métodos estáticos aceptan un conjunto de hasta ocho valores que se van a combinar.
  • Dos métodos de instancia funcionan de forma de streaming, aceptando valores de uno en uno.

Advertencia

Se recomienda considerar los códigos hash como detalles de implementación, ya que la implementación puede cambiar entre versiones de ensamblado. No almacene códigos hash generados por HashCode en estructuras serializadas, por ejemplo, en disco. HashCode usa una inicialización aleatoria inicializada estáticamente para aplicar este procedimiento recomendado, lo que significa que los códigos hash solo son deterministas dentro del ámbito de un proceso de sistema operativo.

Métodos

Add<T>(T)

Agrega un valor único al código hash.

Add<T>(T, IEqualityComparer<T>)

Agrega un valor único al código hash al especificar el tipo que proporciona la función de código hash.

AddBytes(ReadOnlySpan<Byte>)

Agrega un intervalo de bytes al código hash.

Combine<T1,T2,T3,T4,T5,T6,T7,T8>(T1, T2, T3, T4, T5, T6, T7, T8)

Combina ocho valores en un código hash.

Combine<T1,T2,T3,T4,T5,T6,T7>(T1, T2, T3, T4, T5, T6, T7)

Combina siete valores en un código hash.

Combine<T1,T2,T3,T4,T5,T6>(T1, T2, T3, T4, T5, T6)

Combina seis valores en un código hash.

Combine<T1,T2,T3,T4,T5>(T1, T2, T3, T4, T5)

Combina cinco valores en un código hash.

Combine<T1,T2,T3,T4>(T1, T2, T3, T4)

Combina cuatro valores en un código hash.

Combine<T1,T2,T3>(T1, T2, T3)

Combina tres valores en un código hash.

Combine<T1,T2>(T1, T2)

Combina dos valores en un código hash.

Combine<T1>(T1)

Difunde el código hash devuelto por el valor especificado.

Equals(Object)
Obsoletos.

Este método no se admite y no se debe llamar.

GetHashCode()
Obsoletos.

Este método no se admite y no se debe llamar.

ToHashCode()

Calcula el código hash final después de invocaciones de Add consecutivas.

Se aplica a

Producto Versiones
.NET Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Standard 2.0, 2.1