Dictionary에서 내가 만든 Class를 키값으로 사용하고 싶을 때가 있는데 이럴 경우

내가 만든 클래스끼리 비교할 수 있도록

Equals메서드와 GetHashCode메서드를 오버라이드 해야한다.

월과 일을 멤버로 갖고 있는 MonthDay라는 클래스를 정의했을 때 이 MonthDay객체를 키로 이용하는 다음 코드를 작성했다.

//MonthDay 객체를 키로 이용하고 각 날짜에 대응하는 휴일을 저장한다.
var dict = new Dictionary<MonthDay, string>
{
    { new MonthDay(6, 6), "현충일" },
    { new MonthDay(8, 15), "광복절" },
    { new MonthDay(10, 3), "개천절" },
}

var monthDay = new MonthDay(8, 15);
var selected = dict[monthDay];    //KeyNotFoundException 예외 발생
Console.WriteLine(selected);

그러나 위 코드를 실행하면 KeyNotFoundException 예외가 발생한다.

제대로 동작시키려면 사용자가 정의한 Month 클래스에서 Equals 메서드와 GetHashCode 메서드를 오버라이드 해야한다.

아래와 같이 클래스 정의 부분에 함수를 오버라이드 해주면 MonthDay 클래스를 딕셔너리의 키로 이용할 수 있다.

class MonthDay
{
    public int Day { get; private set; }
    public int Month { get; private set; }
    public MonthDay(int month, int day)
    {
        this.Month = month;
        this.Day = day;
    }
 
    //MonthDay끼리 비교한다
    public override bool Equals(object obj)
    {
        var other = obj as MonthDay;
        if (other == null)
            throw new ArgumentException();
        return this.Day == other.Day && this.Month == other.Month; 
    }

        //해시코드를 구한다
    public override int GetHashCode()
    {
         return Month.GetHashCode() * 31 + Day.GetHashCode();
    }
}

**해시 코드(해시값)**는 객체의 값을 가지고 일정한 계산을 해서 구한 int 형 값을 말하여

딕셔너리 내부에서는 값을 찾을 때 인덱스로 이용한다.

같은 객체로부터는 항상 같은 해시값이 생성되어야 한다.

그리고 이 해시값을 사용해 본래의 객체를 복원할 수는 없다.

다른 객체가 동일한 해시값을 생성해도 문제가 없다.

그러나 동일한 값이 반환되는 빈도가 높으면 딕셔너리가 가진 빠르다는 장점을 잃게 된다.

다른 객체의 해시값은 최대한 다른 값이 반환되도록 구현해야 한다.