Object.GetHashCode 메서드
정의
중요
일부 정보는 릴리스되기 전에 상당 부분 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적이거나 묵시적인 보증도 하지 않습니다.
기본 해시 함수로 사용됩니다.
public:
virtual int GetHashCode();
public virtual int GetHashCode();
abstract member GetHashCode : unit -> int
override this.GetHashCode : unit -> int
Public Overridable Function GetHashCode () As Integer
반품
현재 개체에 대한 해시 코드입니다.
예제
형식과 Int32 같거나 작은 범위의 숫자 값에 대한 해시 코드를 계산하는 가장 간단한 방법 중 하나는 해당 값을 반환하는 것입니다. 다음 예제는 Number 구조체의 이러한 구현을 설명합니다.
using System;
public struct Number
{
private int n;
public Number(int value)
{
n = value;
}
public int Value
{
get { return n; }
}
public override bool Equals(Object obj)
{
if (obj == null || ! (obj is Number))
return false;
else
return n == ((Number) obj).n;
}
public override int GetHashCode()
{
return n;
}
public override string ToString()
{
return n.ToString();
}
}
public class Example1
{
public static void Main()
{
Random rnd = new Random();
for (int ctr = 0; ctr <= 9; ctr++) {
int randomN = rnd.Next(Int32.MinValue, Int32.MaxValue);
Number n = new Number(randomN);
Console.WriteLine("n = {0,12}, hash code = {1,12}", n, n.GetHashCode());
}
}
}
// The example displays output like the following:
// n = -634398368, hash code = -634398368
// n = 2136747730, hash code = 2136747730
// n = -1973417279, hash code = -1973417279
// n = 1101478715, hash code = 1101478715
// n = 2078057429, hash code = 2078057429
// n = -334489950, hash code = -334489950
// n = -68958230, hash code = -68958230
// n = -379951485, hash code = -379951485
// n = -31553685, hash code = -31553685
// n = 2105429592, hash code = 2105429592
open System
[<Struct; CustomEquality; NoComparison>]
type Number(value: int) =
member _.Value = value
override _.Equals(obj) =
match obj with
| :? Number as n ->
n.Value = value
| _ -> false
override _.GetHashCode() =
value
override _.ToString() =
string value
let rnd = Random()
for _ = 0 to 9 do
let randomN = rnd.Next(Int32.MinValue, Int32.MaxValue)
let n = Number randomN
printfn $"n = {n,12}, hash code = {n.GetHashCode(),12}"
// The example displays output like the following:
// n = -634398368, hash code = -634398368
// n = 2136747730, hash code = 2136747730
// n = -1973417279, hash code = -1973417279
// n = 1101478715, hash code = 1101478715
// n = 2078057429, hash code = 2078057429
// n = -334489950, hash code = -334489950
// n = -68958230, hash code = -68958230
// n = -379951485, hash code = -379951485
// n = -31553685, hash code = -31553685
// n = 2105429592, hash code = 2105429592
Public Structure Number
Private n As Integer
Public Sub New(value As Integer)
n = value
End Sub
Public ReadOnly Property Value As Integer
Get
Return n
End Get
End Property
Public Overrides Function Equals(obj As Object) As Boolean
If obj Is Nothing OrElse Not TypeOf obj Is Number Then
Return False
Else
Return n = CType(obj, Number).n
End If
End Function
Public Overrides Function GetHashCode() As Integer
Return n
End Function
Public Overrides Function ToString() As String
Return n.ToString()
End Function
End Structure
Module Example1
Public Sub Main()
Dim rnd As New Random()
For ctr As Integer = 0 To 9
Dim randomN As Integer = rnd.Next(Int32.MinValue, Int32.MaxValue)
Dim n As New Number(randomN)
Console.WriteLine("n = {0,12}, hash code = {1,12}", n, n.GetHashCode())
Next
End Sub
End Module
' The example displays output like the following:
' n = -634398368, hash code = -634398368
' n = 2136747730, hash code = 2136747730
' n = -1973417279, hash code = -1973417279
' n = 1101478715, hash code = 1101478715
' n = 2078057429, hash code = 2078057429
' n = -334489950, hash code = -334489950
' n = -68958230, hash code = -68958230
' n = -379951485, hash code = -379951485
' n = -31553685, hash code = -31553685
' n = 2105429592, hash code = 2105429592
형식에는 해시 코드 생성에 참여할 수 있는 여러 데이터 필드가 있는 경우가 많습니다. 해시 코드를 생성하는 한 가지 방법은 다음 예제와 같이 작업을 사용하여 XOR (eXclusive OR) 이러한 필드를 결합하는 것입니다.
using System;
// A type that represents a 2-D point.
public struct Point2
{
private int x;
private int y;
public Point2(int x, int y)
{
this.x = x;
this.y = y;
}
public override bool Equals(Object obj)
{
if (! (obj is Point2)) return false;
Point2 p = (Point2) obj;
return x == p.x & y == p.y;
}
public override int GetHashCode()
{
return x ^ y;
}
}
public class Example3
{
public static void Main()
{
Point2 pt = new Point2(5, 8);
Console.WriteLine(pt.GetHashCode());
pt = new Point2(8, 5);
Console.WriteLine(pt.GetHashCode());
}
}
// The example displays the following output:
// 13
// 13
// A type that represents a 2-D point.
[<Struct; CustomEquality; NoComparison>]
type Point(x: int, y: int) =
member _.X = x
member _.Y = y
override _.Equals(obj) =
match obj with
| :? Point as p ->
x = p.X && y = p.Y
| _ ->
false
override _.GetHashCode() =
x ^^^ y
let pt = Point(5, 8)
printfn $"{pt.GetHashCode()}"
let pt2 = Point(8, 5)
printfn $"{pt2.GetHashCode()}"
// The example displays the following output:
// 13
// 13
' A type that represents a 2-D point.
Public Structure Point3
Private x As Integer
Private y As Integer
Public Sub New(x As Integer, y As Integer)
Me.x = x
Me.y = y
End Sub
Public Overrides Function Equals(obj As Object) As Boolean
If Not TypeOf obj Is Point3 Then Return False
Dim p As Point3 = CType(obj, Point3)
Return x = p.x And y = p.y
End Function
Public Overrides Function GetHashCode() As Integer
Return x Xor y
End Function
End Structure
Public Module Example3
Public Sub Main()
Dim pt As New Point3(5, 8)
Console.WriteLine(pt.GetHashCode())
pt = New Point3(8, 5)
Console.WriteLine(pt.GetHashCode())
End Sub
End Module
이전 예제에서는 (n1, n2) 및 (n2, n1)에 대해 동일한 해시 코드를 반환하므로 바람직한 것보다 더 많은 충돌을 생성할 수 있습니다. .NET 5 이상에서 권장되는 솔루션은 HashCode.Combine. 대칭 문제를 피하고 Tuple 개체의 오버헤드 없이 잘 분산된 해시 코드를 생성합니다.
using System;
public struct Point3
{
private int x;
private int y;
public Point3(int x, int y)
{
this.x = x;
this.y = y;
}
public override bool Equals(Object obj)
{
if (obj is Point3)
{
Point3 p = (Point3) obj;
return x == p.x & y == p.y;
}
else
{
return false;
}
}
public override int GetHashCode()
{
return HashCode.Combine(x, y);
}
}
public class Example
{
public static void Main()
{
Point3 pt = new Point3(5, 8);
Console.WriteLine(pt.GetHashCode());
pt = new Point3(8, 5);
Console.WriteLine(pt.GetHashCode());
}
}
// The example displays output similar to the following.
// Note: HashCode.Combine results are not stable across .NET versions.
// 185727722
// -363254492
[<Struct; CustomEquality; NoComparison>]
type Point(x: int, y: int) =
member _.X = x
member _.Y = y
override _.Equals(obj) =
match obj with
| :? Point as p ->
x = p.X && y = p.Y
| _ ->
false
override _.GetHashCode() =
System.HashCode.Combine(x, y)
let pt = Point(5, 8)
printfn $"{pt.GetHashCode()}"
let pt2 = Point(8, 5)
printfn $"{pt2.GetHashCode()}"
// The example displays output similar to the following.
// Note: HashCode.Combine results are not stable across .NET versions.
// 185727722
// -363254492
Public Structure Point
Private x As Integer
Private y As Integer
Public Sub New(x As Integer, y As Integer)
Me.x = x
Me.y = y
End Sub
Public Overrides Function Equals(obj As Object) As Boolean
If Not TypeOf obj Is Point Then Return False
Dim p As Point = CType(obj, Point)
Return x = p.x And y = p.y
End Function
Public Overrides Function GetHashCode() As Integer
Return HashCode.Combine(x, y)
End Function
End Structure
Public Module Example
Public Sub Main()
Dim pt As New Point(5, 8)
Console.WriteLine(pt.GetHashCode())
pt = New Point(8, 5)
Console.WriteLine(pt.GetHashCode())
End Sub
End Module
' The example displays output similar to the following.
' Note: HashCode.Combine results are not stable across .NET versions.
' 185727722
' -363254492
설명
이 메서드는 GetHashCode 개체 같음의 빠른 검사가 필요한 알고리즘에 대한 해시 코드를 제공합니다. 해시 코드는 클래스, Dictionary<TKey,TValue> 클래스 또는 클래스에서 파생된 형식과 같은 Hashtable 해시 기반 컬렉션에서 DictionaryBase 개체를 삽입하고 식별하는 데 사용되는 숫자 값입니다.
비고
해시 테이블에서 해시 코드를 사용하는 방법과 몇 가지 추가 해시 코드 알고리즘에 대한 자세한 내용은 Wikipedia의 해시 함수 항목을 참조하세요.
동일한 두 개체는 동일한 해시 코드를 반환합니다. 그러나 반대는 true가 아닙니다. 다른(같지 않은) 개체에는 동일한 해시 코드가 있을 수 있기 때문에 동일한 해시 코드가 개체 같음을 의미하지는 않습니다. 또한 .NET GetHashCode 메서드의 기본 구현을 보장하지 않으며, 이 메서드가 반환하는 값은 32비트 및 64비트 플랫폼과 같은 .NET 구현과 플랫폼 간에 다를 수 있습니다. 이러한 이유로 이 메서드의 기본 구현을 해시 용도로 고유한 개체 식별자로 사용하지 마세요. 두 가지 결과는 다음과 같습니다.
- 동일한 해시 코드가 개체 같음을 암시한다고 가정해서는 안 됩니다.
- 동일한 개체가 애플리케이션 도메인, 프로세스 및 플랫폼에서 해시할 수 있으므로 생성된 애플리케이션 도메인 외부에서 해시 코드를 유지하거나 사용하면 안 됩니다.
Warning
해시 코드는 해시 테이블을 기반으로 하는 컬렉션에서 효율적인 삽입 및 조회를 위한 것입니다. 해시 코드는 영구 값이 아닙니다. 이러한 이유로 다음을 수행합니다.
- 해시 코드 값을 직렬화하거나 데이터베이스에 저장하지 마세요.
- 키 컬렉션에서 개체를 검색하는 키로 해시 코드를 사용하지 마세요.
- 애플리케이션 도메인 또는 프로세스 간에 해시 코드를 보내지 마세요. 경우에 따라 해시 코드는 프로세스별 또는 애플리케이션별 도메인 기준으로 계산될 수 있습니다.
- 암호화에 강력한 해시가 필요한 경우 암호화 해시 함수에서 반환하는 값 대신 해시 코드를 사용하지 마세요. 암호화 해시의 경우, System.Security.Cryptography.HashAlgorithm 클래스 또는 System.Security.Cryptography.KeyedHashAlgorithm 클래스에서 파생된 클래스를 사용합니다.
- 두 개체가 같은지 여부를 확인하기 위해 해시 코드의 같음을 테스트하지 마세요. (같지 않은 개체는 동일한 해시 코드를 가질 수 있습니다.) 같음을 테스트하려면 메서드 ReferenceEquals 또는 메서드 Equals를 호출하세요.
GetHashCode 메서드는 파생된 형식에 의해 재정의될 수 있습니다. 재정의되지 않은 경우 GetHashCode 참조 형식에 대한 해시 코드는 개체의 참조를 기반으로 해시 코드를 계산하는 기본 클래스의 메서드를 호출 Object.GetHashCode 하여 계산됩니다. 자세한 내용은 다음을 참조하세요 RuntimeHelpers.GetHashCode. 즉, 메서드가 반환 ReferenceEquals 하는 두 개체에는 true 동일한 해시 코드가 있습니다. 값 형식이 GetHashCode을(를) 재정의하지 않으면 기본 클래스의 ValueType.GetHashCode 메서드는 리플렉션을 사용하여 형식 필드의 값을 기반으로 해시 코드를 계산합니다. 즉, 필드 값이 같은 값이 있는 값 형식에는 해시 코드가 같습니다.
GetHashCode를 재정의하는 방법에 대한 자세한 내용은 "상속자 참고사항" 섹션을 참조하세요.
Warning
GetHashCode 메서드를 재정의하는 경우 Equals도 재정의해야 하며, 그 반대의 경우도 마찬가지입니다. 두 객체가 동등성에 대해 테스트되는 경우 재정의된 Equals 메서드가 true를 반환하면, 재정의된 GetHashCode 메서드는 두 객체에 대해 동일한 값을 반환해야 합니다.
해시 테이블에서 키로 사용되는 개체가 유용한 구현GetHashCode을 제공하지 않는 경우 클래스 생성자의 오버로드 IEqualityComparer 중 하나에 구현을 Hashtable 제공하여 해시 코드 공급자를 지정할 수 있습니다.
상속자 참고
해시 함수는 개체 값에 해당하는 숫자(해시 코드)를 빠르게 생성하는 데 사용됩니다. 해시 함수는 일반적으로 각 형식에 따라 지정되며 고유성을 위해 하나 이상의 인스턴스 필드를 입력으로 사용해야 합니다. 해시 코드는 정적 필드 값을 사용하여 계산해서는 안 됩니다.
파생된 Object클래스의 GetHashCode 경우 파생 클래스 GetHashCode() 가 같음을 참조 같음으로 정의하는 경우에만 메서드가 기본 클래스 구현에 위임할 수 있습니다. 참조 형식에 GetHashCode() 대한 기본 구현은 메서드에서 반환한 해시 코드와 동일한 해시 코드를 반환 GetHashCode(Object) 합니다. 변경할 수 없는 참조 형식에 대해 재정 GetHashCode() 의할 수 있습니다. 일반적으로 변경 가능한 참조 형식의 경우 다음 경우에만 재정 GetHashCode() 의해야 합니다.
변경할 수 없는 필드에서 해시 코드를 계산할 수 있습니다. 또는
개체가 해당 해시 코드를 사용하는 컬렉션에 포함되어 있는 동안 변경 가능한 개체의 해시 코드가 변경되지 않도록 할 수 있습니다.
그렇지 않으면 해시 테이블에서 변경 가능한 개체가 손실된 것으로 생각할 수 있습니다. 변경 가능한 참조 형식에 대해 재정 GetHashCode() 의하도록 선택하는 경우 설명서에서는 개체가 해시 테이블에 저장되는 동안 형식의 사용자가 개체 값을 수정해서는 안 됨을 분명히 해야 합니다.
값 형식의 GetHashCode() 경우 리플렉션을 사용하는 기본 해시 코드 구현을 제공합니다. 성능 향상을 위해 재정의하는 것이 좋습니다.
다양한 방법으로 해시 코드를 계산하는 자세한 내용 및 예제는 예제 섹션을 참조하세요.
해시 함수에는 다음 속성이 있어야 합니다.
두 개체가 같음으로 비교되면 각 개체에 GetHashCode() 대한 메서드는 동일한 값을 반환해야 합니다. 그러나 두 개체가 같 GetHashCode() 음으로 비교되지 않으면 두 개체에 대한 메서드가 서로 다른 값을 반환할 필요가 없습니다.
GetHashCode() 개체의 System.Object.Equals 메서드의 반환 값을 결정하는 개체 상태를 수정하지 않는 한 개체에 대한 메서드는 동일한 해시 코드를 일관되게 반환해야 합니다. 이는 애플리케이션의 현재 실행에만 적용되며 애플리케이션이 다시 실행될 경우 다른 해시 코드를 반환할 수 있습니다.
최상의 성능을 위해 해시 함수는 많은 클러스터형 입력을 포함하여 모든 입력에 대해 짝수 분포를 생성해야 합니다. 개체 상태를 약간 수정하면 최상의 해시 테이블 성능을 위해 결과 해시 코드를 크게 수정해야 한다는 의미입니다.
해시 함수는 컴퓨팅에 저렴해야 합니다.
메서드는 GetHashCode() 예외를 throw해서는 안 됩니다.
예를 들어 클래스에서 GetHashCode() 제공하는 메서드의 구현은 String 동일한 문자열 값에 대해 동일한 해시 코드를 반환합니다. 따라서 두 String 개체는 동일한 문자열 값을 나타내는 경우 동일한 해시 코드를 반환합니다. 또한 이 메서드는 입력이 특정 범위에서 클러스터링된 경우에도 문자열의 모든 문자를 사용하여 합리적으로 임의로 분산된 출력을 생성합니다(예를 들어 문자열에 65,535개의 유니코드 문자가 포함될 수 있더라도 많은 사용자가 낮은 128개의 ASCII 문자만 포함하는 문자열이 있을 수 있음).
클래스에 좋은 해시 함수를 제공하면 해시 테이블에 해당 개체를 추가하는 성능에 큰 영향을 줄 수 있습니다. 해시 함수의 적절한 구현을 제공하는 키가 있는 해시 테이블에서 요소를 검색하는 데는 일정한 시간(예: O(1) 작업)이 필요합니다. 해시 함수의 구현이 좋지 않은 해시 테이블에서 검색 성능은 해시 테이블의 항목 수(예: 해시 테이블의 항목 수인 O(n) 작업 n )에 따라 달라집니다. 악의적인 사용자는 충돌 횟수를 늘리는 데이터를 입력할 수 있으며, 이는 다음 조건에서 해시 테이블에 의존하는 애플리케이션의 성능을 크게 저하시킬 수 있습니다.
해시 함수가 자주 충돌하는 경우
해시 테이블의 개체 비율이 크면 서로 같거나 거의 같은 해시 코드를 생성합니다.
사용자가 해시 코드가 계산되는 데이터를 입력할 때
재정의하는 GetHashCode() 파생 클래스도 재정의 Equals(Object) 하여 동일한 것으로 간주되는 두 개체에 동일한 해시 코드가 있는지 확인해야 합니다. 그렇지 않으면 형식이 Hashtable 제대로 작동하지 않을 수 있습니다.