Ler em inglês

Partilhar via


HashCode Estrutura

Definição

Combina o código hash de vários valores em um único código hash.

public struct HashCode
Herança
HashCode

Exemplos

Os métodos estáticos nessa classe combinam os códigos hash padrão de até oito 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() deve ser chamado no máximo uma vez por instância de HashCode.

Os métodos de instância nessa classe combinam os códigos hash de mais de oito 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.

Os métodos de instância também combinam os códigos de hash produzidos por uma implementação 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.

A HashCode estrutura deve ser passada por referência para outros métodos, pois é um 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.

Comentários

Você pode usar HashCode para combinar vários valores (por exemplo, campos em uma estrutura ou classe) em um único código hash. Essa estrutura tem métodos estáticos e de instância que operam de forma diferente:

  • Os métodos estáticos aceitam um conjunto de até oito valores a serem combinados.
  • Dois métodos de instância operam de forma de streaming, aceitando valores um de cada vez.

Aviso

É recomendável considerar os códigos de hash como um detalhe de implementação, pois a implementação pode mudar entre as versões do assembly. Não armazene códigos hash produzidos por HashCode em estruturas serializadas, por exemplo, no disco. HashCode usa uma semente aleatória inicializada estaticamente para impor essa melhor prática, o que significa que os códigos de hash são apenas determinísticos dentro do escopo de um processo do sistema operacional.

Métodos

Add<T>(T)

Adiciona um único valor ao código hash.

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

Adiciona um único valor ao código hash, especificando o tipo que fornece a função de código hash.

AddBytes(ReadOnlySpan<Byte>)

Adiciona um intervalo de bytes ao código hash.

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

Combina oito valores em um código hash.

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

Combina sete valores em um código hash.

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

Combina seis valores em um código hash.

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

Combina cinco valores em um código hash.

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

Combina quatro valores em um código hash.

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

Combina três valores em um código hash.

Combine<T1,T2>(T1, T2)

Combina dois valores em um código hash.

Combine<T1>(T1)

Difunde o código hash retornado pelo valor especificado.

Equals(Object)
Obsoleto.

Esse método não deve ser usado e não há suporte para ele.

GetHashCode()
Obsoleto.

Esse método não deve ser usado e não há suporte para ele.

ToHashCode()

Calcula o código hash final após invocações de Add consecutivas.

Aplica-se a

Produto Versões
.NET Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Standard 2.0, 2.1