閱讀英文

共用方式為


HashCode 結構

定義

將多個值的雜湊碼合併成單一雜湊碼。

public struct HashCode
繼承
HashCode

範例

這個類別中的靜態方法會結合 最多八 個值的預設哈希碼。

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.

重要

ToHashCode() 每個實例 HashCode最多必須呼叫一次。

這個類別中的實例方法會結合 超過八 個值的哈希碼。

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.

實例方法也會結合特定 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.

結構 HashCode 必須以參考方式傳遞至其他方法,因為它是實值型別。

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.

備註

您可以使用 HashCode 將多個值結合 (例如,結構或類別上的欄位) 合併成單一哈希程序代碼。 此結構具有以不同方式運作的靜態和實例方法:

  • 靜態方法接受最多八個值組合。
  • 兩個實例方法會以串流方式運作,一次接受一個值。

警告

最佳做法是將哈希程式代碼視為實作詳細數據,因為實作可能會在元件版本之間變更。 請勿將 所產生的 HashCode 哈希碼儲存在串行化結構中,例如磁碟上。 HashCode 會使用靜態初始化的隨機種子來強制執行此最佳做法,這表示哈希碼只會在操作系統進程的範圍內具決定性。

方法

Add<T>(T)

將單一值新增至雜湊碼。

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

將單一值新增至雜湊碼,以指定提供雜湊碼函式的型別。

AddBytes(ReadOnlySpan<Byte>)

將位元組範圍新增至哈希程序代碼。

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

將八個值合併成雜湊碼。

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

將七個值合併成一個雜湊碼。

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

將六個值合併成雜湊碼。

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

將五個值合併成雜湊碼。

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

將四個值合併成雜湊碼。

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

將三個值合併成雜湊碼。

Combine<T1,T2>(T1, T2)

將兩個值合併成雜湊碼。

Combine<T1>(T1)

擴散指定值所傳回的雜湊碼。

Equals(Object)
已淘汰.

不支援且不應該呼叫這個方法。

GetHashCode()
已淘汰.

不支援且不應該呼叫這個方法。

ToHashCode()

計算在連續 Add 引動過程之後的最終雜湊碼。

適用於

產品 版本
.NET Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Standard 2.0, 2.1