HashCode Struktur

Definition

Kombiniert den Hashcode für mehrere Werte zu einem einzelnen Hashcode.

public value class HashCode
public struct HashCode
type HashCode = struct
Public Structure HashCode
Vererbung
HashCode

Beispiele

Die statischen Methoden in dieser Klasse kombinieren die Standardhashcodes mit bis zu acht Werten.

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.
open System
open System.Collections.Generic

[<Struct; CustomEquality; NoComparison>]
type OrderOrderLine(orderId: int, orderLineId: int) =
    member _.OrderId = orderId
    member _.OrderLineId = orderLineId

    override _.GetHashCode() = 
        HashCode.Combine(orderId, orderLineId)

    override this.Equals(obj) =
        match obj with
        | :? OrderOrderLine as o -> (this :> IEquatable<_>).Equals o
        | _ -> false

    interface IEquatable<OrderOrderLine> with
        member _.Equals(other: OrderOrderLine) = 
            orderId = other.OrderId && orderLineId = other.OrderLineId

let set =
    HashSet<OrderOrderLine> [ OrderOrderLine(1, 1); OrderOrderLine(1, 1); OrderOrderLine(1, 2) ]
printfn $"Item count: {set.Count}."

// The example displays the following output:
// Item count: 2.
Public Structure OrderOrderLine
    Implements IEquatable(Of OrderOrderLine)

    Public ReadOnly Property OrderId As Integer
    Public ReadOnly Property OrderLineId As Integer

    Public Sub New(ByVal orderId As Integer, ByVal orderLineId As Integer)
        Me.OrderId = orderId
        Me.OrderLineId = orderLineId
    End Sub

    Public Overrides Function Equals(obj As Object) As Boolean
        Return (TypeOf obj Is OrderOrderLine) AndAlso Equals(DirectCast(obj, OrderOrderLine))
    End Function

    Public Overloads Function Equals(other As OrderOrderLine) As Boolean Implements IEquatable(Of OrderOrderLine).Equals
        Return OrderId = other.OrderId AndAlso
               OrderLineId = other.OrderLineId
    End Function

    Public Overrides Function GetHashCode() As Integer
        Return HashCode.Combine(OrderId, OrderLineId)
    End Function

End Structure

Module Program

    Sub Main(args As String())
        Dim hashSet As HashSet(Of OrderOrderLine) = New HashSet(Of OrderOrderLine)
        hashSet.Add(New OrderOrderLine(1, 1))
        hashSet.Add(New OrderOrderLine(1, 1))
        hashSet.Add(New OrderOrderLine(1, 2))
        Console.WriteLine($"Item count: {hashSet.Count}")
    End Sub

End Module
' The example displays the following output:
' Item count: 2.

Wichtig

ToHashCode()muss höchstens einmal pro instance von HashCodeaufgerufen werden.

Die instance Methoden in dieser Klasse kombinieren die Hashcodes von mehr als acht Werten.

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.
open System
open System.Collections.Generic

[<Struct; CustomEquality; NoComparison>]
type Path([<ParamArray>]segments: string[]) = 
    member _.Segments = 
        Array.AsReadOnly segments

    override this.Equals(obj) =
        match obj with
        | :? Path as o -> (this :> IEquatable<_>).Equals(o)
        | _ -> false

    interface IEquatable<Path> with
        member this.Equals(other: Path) =
            Object.ReferenceEquals(this.Segments, other.Segments) ||
            not (isNull this.Segments) && 
            not (isNull other.Segments) &&
            this.Segments.Count = other.Segments.Count &&
            Seq.forall2 (=) this.Segments other.Segments 

    override this.GetHashCode() =
        let hash = HashCode()

        for i = 0 to this.Segments.Count - 1 do
            hash.Add this.Segments[i]
        hash.ToHashCode()

let set = 
    HashSet<Path> [
        Path("C:", "tmp", "file.txt")
        Path("C:", "tmp", "file.tmp")
        Path("C:", "tmp", "file.txt") ]
        
printfn $"Item count: {set.Count}."

// The example displays the following output:
// Item count: 2.
Public Structure Path
    Implements IEquatable(Of Path)

    Public ReadOnly Property Segments As IReadOnlyList(Of String)

    Public Sub New(ParamArray ByVal segments() As String)
        Me.Segments = segments
    End Sub

    Public Overrides Function Equals(obj As Object) As Boolean
        Return (TypeOf obj Is Path) AndAlso Equals(DirectCast(obj, Path))
    End Function

    Public Overloads Function Equals(other As Path) As Boolean Implements IEquatable(Of Path).Equals
        If ReferenceEquals(Segments, other.Segments) Then Return True
        If Segments Is Nothing OrElse other.Segments Is Nothing Then Return False
        If Segments.Count <> other.Segments.Count Then Return False

        For i As Integer = 0 To Segments.Count - 1
            If Not String.Equals(Segments(i), other.Segments(i)) Then Return False
        Next

        Return True
    End Function

    Public Overrides Function GetHashCode() As Integer
        Dim hash As HashCode = New HashCode()

        For i As Integer = 0 To Segments?.Count - 1
            hash.Add(Segments(i))
        Next

        Return hash.ToHashCode()
    End Function

End Structure

Module Program

    Sub Main(args As String())
        Dim hashSet As HashSet(Of Path) = New HashSet(Of Path) From {
            New Path("C:", "tmp", "file.txt"),
            New Path("C:", "tmp", "file.txt"),
            New Path("C:", "tmp", "file.tmp")
        }
        Console.WriteLine($"Item count: {hashSet.Count}.")
    End Sub

End Module
' The example displays the following output:
' Item count: 2.

Die instance Methoden kombinieren auch die Hashcodes, die von einer bestimmten IEqualityComparer<T> Implementierung erstellt wurden.

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.
open System
open System.Collections.Generic

[<Struct; CustomEquality; NoComparison>]
type Path([<ParamArray>]segments: string[]) =
    member _.Segments = 
        Array.AsReadOnly segments

    override this.Equals(obj) =
        match obj with
        | :? Path as o -> (this :> IEquatable<_>).Equals(o)
        | _ -> false

    interface IEquatable<Path> with
        member this.Equals(other: Path) =
            Object.ReferenceEquals(this.Segments, other.Segments) ||
            not (isNull this.Segments) && 
            not (isNull other.Segments) &&
            this.Segments.Count = other.Segments.Count &&
            Seq.forall2 (fun x y -> String.Equals(x, y, StringComparison.OrdinalIgnoreCase)) this.Segments other.Segments 

    override this.GetHashCode() =
        let hash = HashCode()

        for i = 0 to this.Segments.Count - 1 do
            hash.Add(this.Segments[i], StringComparer.OrdinalIgnoreCase)
        hash.ToHashCode()

let set = 
    HashSet<Path> [
        Path("C:", "tmp", "file.txt")
        Path("C:", "tmp", "file.tmp")
        Path("C:", "tmp", "file.txt") ]

printfn $"Item count: {set.Count}."

// The example displays the following output:
// Item count: 1.
Public Structure Path
    Implements IEquatable(Of Path)

    Public ReadOnly Property Segments As IReadOnlyList(Of String)

    Public Sub New(ParamArray ByVal segments() As String)
        Me.Segments = segments
    End Sub

    Public Overrides Function Equals(obj As Object) As Boolean
        Return (TypeOf obj Is Path) AndAlso Equals(DirectCast(obj, Path))
    End Function

    Public Overloads Function Equals(other As Path) As Boolean Implements IEquatable(Of Path).Equals
        If ReferenceEquals(Segments, other.Segments) Then Return True
        If Segments Is Nothing OrElse other.Segments Is Nothing Then Return False
        If Segments.Count <> other.Segments.Count Then Return False

        For i As Integer = 0 To Segments.Count - 1
            If Not String.Equals(Segments(i), other.Segments(i), StringComparison.OrdinalIgnoreCase) Then Return False
        Next

        Return True
    End Function

    Public Overrides Function GetHashCode() As Integer
        Dim hash As HashCode = New HashCode()

        For i As Integer = 0 To Segments?.Count - 1
            hash.Add(Segments(i), StringComparer.OrdinalIgnoreCase)
        Next

        Return hash.ToHashCode()
    End Function
    
End Structure

Module Program

    Sub Main(args As String())
        Dim hashSet As HashSet(Of Path) = New HashSet(Of Path) From {
            New Path("C:", "tmp", "file.txt"),
            New Path("C:", "TMP", "file.txt"),
            New Path("C:", "tmp", "FILE.TXT")
        }
        Console.WriteLine($"Item count: {hashSet.Count}.")
    End Sub

End Module
' The example displays the following output:
' Item count: 1.

Die HashCode -Struktur muss als Verweis an andere Methoden übergeben werden, da es sich um einen Werttyp handelt.

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.
open System
open System.Collections.Generic

module PlatformUtils =
    let pathEquals a b = String.Equals(a, b, StringComparison.OrdinalIgnoreCase)
    let addPath (hash: byref<HashCode>) path = hash.Add(path, StringComparer.OrdinalIgnoreCase)

[<Struct; CustomEquality; NoComparison>]
type Path([<ParamArray>]segments: string[]) =
    member _.Segments = 
        Array.AsReadOnly segments

    override this.Equals(obj) =
        match obj with
        | :? Path as o -> (this :> IEquatable<_>).Equals(o)
        | _ -> false

    interface IEquatable<Path> with
        member this.Equals(other: Path) =
            Object.ReferenceEquals(this.Segments, other.Segments) ||
            not (isNull this.Segments) && 
            not (isNull other.Segments) &&
            this.Segments.Count = other.Segments.Count &&
            Seq.forall2 PlatformUtils.pathEquals this.Segments other.Segments 

    override this.GetHashCode() =
        let mutable hash = HashCode()

        for i = 0 to this.Segments.Count - 1 do
            PlatformUtils.addPath &hash this.Segments[i]
        hash.ToHashCode()


let set =
    HashSet<Path> [
        Path("C:", "tmp", "file.txt")
        Path("C:", "TMP", "file.txt")
        Path("C:", "tmp", "FILE.TXT") ]

printfn $"Item count: {set.Count}."

// The example displays the following output:
// Item count: 1.
Public Structure Path
    Implements IEquatable(Of Path)

    Public ReadOnly Property Segments As IReadOnlyList(Of String)

    Public Sub New(ParamArray ByVal segments() As String)
        Me.Segments = segments
    End Sub

    Public Overrides Function Equals(obj As Object) As Boolean
        Return (TypeOf obj Is Path) AndAlso Equals(DirectCast(obj, Path))
    End Function

    Public Overloads Function Equals(other As Path) As Boolean Implements IEquatable(Of Path).Equals
        If ReferenceEquals(Segments, other.Segments) Then Return True
        If Segments Is Nothing OrElse other.Segments Is Nothing Then Return False
        If Segments.Count <> other.Segments.Count Then Return False

        For i As Integer = 0 To Segments.Count - 1
            If Not PathEquals(Segments(i), other.Segments(i)) Then Return False
        Next

        Return True
    End Function

    Public Overrides Function GetHashCode() As Integer
        Dim hash As HashCode = New HashCode()

        For i As Integer = 0 To Segments?.Count - 1
            AddPath(hash, Segments(i))
        Next

        Return hash.ToHashCode()
    End Function
    
End Structure

Friend Module PlatformUtils

    Public Function PathEquals(ByVal a As String, ByVal b As String) As Boolean
        Return String.Equals(a, b, StringComparison.OrdinalIgnoreCase)
    End Function

    Public Sub AddPath(ByRef hash As HashCode, ByVal path As String)
        hash.Add(path, StringComparer.OrdinalIgnoreCase)
    End Sub

End Module

Module Program

    Sub Main(args As String())
        Dim hashSet As HashSet(Of Path) = New HashSet(Of Path) From {
            New Path("C:", "tmp", "file.txt"),
            New Path("C:", "TMP", "file.txt"),
            New Path("C:", "tmp", "FILE.TXT")
        }
        Console.WriteLine($"Item count: {hashSet.Count}.")
    End Sub

End Module
' The example displays the following output:
' Item count: 1.

Hinweise

Sie können verwenden HashCode , um mehrere Werte (z. B. Felder in einer Struktur oder Klasse) in einem einzelnen Hashcode zu kombinieren. Diese Struktur verfügt über statische und instance Methoden, die unterschiedlich funktionieren:

  • Die statischen Methoden akzeptieren einen Satz von bis zu acht Werten, die kombiniert werden sollen.
  • Zwei instance Methoden funktionieren auf Streaming-Weise und akzeptieren werte einzeln.

Warnung

Es empfiehlt sich, Hashcodes als Implementierungsdetail zu betrachten, da sich die Implementierung zwischen Assemblyversionen ändern kann. Speichern Sie keine Hashcodes, die von HashCode in serialisierten Strukturen erstellt werden, z. B. auf dem Datenträger. HashCode verwendet einen statisch initialisierten zufälligen Ausgangswert, um diese bewährte Methode zu erzwingen, was bedeutet, dass die Hashcodes nur innerhalb des Bereichs eines Betriebssystemprozesses deterministisch sind.

Methoden

Add<T>(T)

Fügt einen einzelnen Wert zum Hashcode hinzu.

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

Fügt einen einzelnen Wert zum Hashcode hinzu, der den Typ angibt, der die Hashcodefunktion bereitstellt.

AddBytes(ReadOnlySpan<Byte>)

Fügt dem Hashcode eine Bytespanne hinzu.

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

Kombiniert sieben Werte zu einem Hashcode.

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

Kombiniert sieben Werte in einem Hashcode.

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

Kombiniert sechs Werte zu einem Hashcode.

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

Kombiniert fünf Werte zu einem Hashcode.

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

Kombiniert vier Werte zu einem Hashcode.

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

Kombiniert drei Werte zu einem Hashcode.

Combine<T1,T2>(T1, T2)

Kombiniert zwei Werte zu einem Hashcode.

Combine<T1>(T1)

Verteilt den Hashcode, der vom angegebenen Wert zurückgegeben wird.

Equals(Object)
Veraltet.

Diese Methode wird nicht unterstützt und sollte nicht aufgerufen werden.

GetHashCode()
Veraltet.

Diese Methode wird nicht unterstützt und sollte nicht aufgerufen werden.

ToHashCode()

Berechnet den endgültigen Hashcode nach aufeinanderfolgenden Aufrufen von Add.

Gilt für: