본문 바로가기
프로그래밍/C#

C# Equals()과 GetHashCode()를 함께 재정의 해야하는 이유

by bantomak 2023. 3. 23.

우리가 맞이하는 상황

프로그래밍을 하다보면 하나 이상의 필드를 Key값으로 설정하여 비교하게 되는 경우가 생기게 됩니다.

그리고 평소처럼 분명 같은 키값을 가진 객체를 ContainsKey() 함수로 비교하면 일치하지 않는다고 나올겁니다.

 

hash 값을 사용하는 Collection(HashTable, Dictionary, ConcurrentDictionary)에서 ContainsKey로 실행하면 우선 GetHashCode() 메서드를 비교하고 그 다음에 Equals() 메서드를 실행합니다. 아무리 Equals() 메서드를 열심히 변경해도 그 앞쪽에서 비교가 일어나서 메서드가 실행되지 않습니다.

 

메서드 실행 순서

이 문제를 해결하기 위하여

하나 이상의 필드를 Key값으로 비교하기 위해서는 해당 클래스의 Equals 함수와 GetHashCode 함수를 재정의해야합니다. (해시코드 계열 컨테이너를 사용하는 경우가 아니라면 상관없지만 다수의 사람이 작업하는 경우 어떻게 사용될지 예상할 수 없기때문에 보통 같이 재정의해서 사용합니다.)

 

enum eEnum
{
    item1,
    item2,
}

class Foo
{
    public eEnum type;
    public int subtype;

    public override bool Equals(object obj)
    {
        return obj is Foo foo &&
               type == foo.type &&
               subtype == foo.subtype;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(type, subtype);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Dictionary<Foo, int> myDic = new Dictionary<Foo, int>();

        myDic.Add(new Foo() { type = eEnum.item1, subtype = 2 }, 1);

        var target = new Foo() { type = eEnum.item1, subtype = 2 };
        if (myDic.ContainsKey(target))
        {
            Console.WriteLine("match");
        }
        else
        {
            Console.WriteLine("not match");
        }
    }
}

 

'프로그래밍 > C#' 카테고리의 다른 글

C# 코드 컴파일 단계에 대해서  (2) 2023.03.29
C# Discards _의 정체  (9) 2023.03.23
C# 괄호 알아보기  (19) 2023.03.20
C# 람다(Lambda)에 대해서  (4) 2023.03.20
C# 네이밍 규칙에 대해서  (1) 2023.03.15

댓글