Section 6.1: 바람직한 GetHashCode 재정의하기

GetHashCodeDictionary<>HashTable 사용에 있어 성능에 지대한 영향을 미치게 된다.

바람직한 GetHashCode 메소드란:

  • 균일한 분포 (distribution) 를 가져야 한다.
    • 임의의 instance 에 대해, 값으로 반환될 수 있는 확률은 모든 integer 값들이 거의 동일하게 가져야 한다.
    • 만약 각각의 instance 들에 대해 동일한 integer 를 반환하게되어 있다면 (예: 언제나 상수 '999' 만을 반환), 성능 저하가 심각하게 일어날 것이다.
  • 빠르게 동작해야 한다.
    • 이 메소드는 (느린 동작을 특징으로 갖는) 암호화 hash 값을 생성하기 위한 것이 아니다.
    • hash 함수가 느려질수록, 사용자의 dictionary 역시 마찬가지로 느려질 것이다.
  • Equals 가 true 로 평가 (evaluate) 되는 두개의 instance 에 대해서는 동일한 HashCode 를 반환해야 한다.
    • 그렇지 않은 경우 (예: GetHashCode 가 난수를 반환한다거나), ListDictionary 혹은 그 비슷한 것들에서 요소 검색에 실패할 수 있다.

GetHashCode 를 구현하는 좋은 방법 중 하나는 소수 하나를 시작값으로 하여, 각 field 들의 hashcode 를 다른 소수와 곱하여 더해 나가는 것이다:

public override int GetHashCode() { unchecked // Overflow 가 발생한다해도 wrap 시키면 되므로 문제가 없다 { int hash = 3049; // 시작 값 (소수) // 이 위치에 적절한 null 확인 등의 코드가 필요할 것이다 hash = hash * 5039 + field1.GetHashCode(); hash = hash * 883 + field2.GetHashCode(); hash = hash * 9719 + field3.GetHashCode(); return hash; } }

Equals 메소드에서 사용되는 field 들만 hash 값 연산에 사용되어야 함에 주의하자.

만약 동일한 타입을 Dictionary / HashTable 들에 대하여 각각 다른 방법으로 다루어야 하는 필요가 있는 경우에는, IEqualityComparer 를 사용할 수 있다.

본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

+ Recent posts