Hash Code Struct

Definition

Combines the hash code for multiple values into a single hash code.

In this article

public value class HashCode

public struct HashCode

type HashCode = struct

Public Structure HashCode

Inheritance Object ValueType HashCode

Remarks

You can use HashCode to combine multiple values (for example, fields on a structure or class) into a single hash code. This structure operates in one of two ways:

Static methods that accept a set of up to eight values to combine.

Two instance methods that operate in a streaming fashion, accepting values one at a time.

Warning It is best-practice to consider hash codes as an implementation detail, as the implementation may change across assembly versions. Do not store hash codes produced by HashCode in serialized structures, for example, on-disk. HashCode uses a statically initialized random seed to enforce this best practice, meaning that the hash codes are only deterministic within the scope of an operating system process.

Static Methods

The static methods combine the default hash codes of up to eight values.

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.

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.

Instance Methods

Important ToHashCode() must be called at most once per instance of HashCode.

The instance methods combine the hash codes of more than eight values.

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.

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.

The instance methods also combine the hash codes produced by a specific IEqualityComparer<T> implementation.

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.

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.

The HashCode structure must be passed by-reference to other methods, as it is a value type.

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.

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.

Methods

Applies to