C# Почему нужно переопределять GetHashCode и Equals вместе?


#1

Почему рекомендуют переопределять GetHashCode и Equals вместе, хотя в своих программах нам не всегда нужны оба данных метода, а достаточно только переопределения одного из них, например, метода Equals.


#2

Никогда не известно понадобится ли Вам или кому-либо еще данная реализация. Принято что при создании сложной логики, собственных структур данных Вы должны описать внутри структуры все краевые случаи работы, чтобы можно было в любой момент взять и воспользоваться без опаски что что-то может не работать.


#3

Тогда у меня возникает следующий вопрос: как лучше всего реализовать переопределённый метод GetHashCode? Ведь Equals можно логически сверить состояние экземпляра, а GetHashCode должен возвращать уникальные значения для каждого нового экземпляра.


#4

Видел несколько предложений по поводу переопределения метода GetHashCode.

1 способ:
взять два простых числа (например, 11 и 7) и проделать следующую процедуру:

public override int GetHashCode()
{
    unchecked
    {
        int hash = 11;
        hash = hash * 7 + field1.GetHashCode();
        hash = hash * 7 + field2.GetHashCode();
        // и так далее для всех существующих полей в классе
        return hash;
    }
}

2 способ:
поместить все поля в анонимный тип/ кортеж и вызвать на нём GetHashCode

public override int GetHashCode()
{
    return new { field1, field2, field3 }.GetHashCode();
    // return (field1, field2, field3).GetHashCode();
}

3 способ:
в случае если в классе 2 поля, то можно в качестве хешкода кода вернуть результат выполнения побитовой операции исключающее или над ними

public override int GetHashCode()
{
    return field1 ^ field2;
}

Также можете почитать статью о хешовых функциях здесь.