HashCode 結構
定義
重要
部分資訊涉及發行前產品,在發行之前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
將多個值的雜湊碼合併成單一雜湊碼。
public value class HashCode
public struct HashCode
type HashCode = struct
Public Structure 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.
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.
重要
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.
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.
實例方法也會結合特定 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.
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.
結構 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.
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.
備註
您可以使用 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 引動過程之後的最終雜湊碼。 |