Хешкод, переопределение метода GetHashCode

Рейтинг: 4Ответов: 1Опубликовано: 25.02.2015

Господа, не могу понять каким образом переопределять метод GetHashCode(). Ведь, насколько я понял, хешкод берется из скрытой переменной в объекте, к которой нет доступа. Тогда как мне его переопределить ?? Если не затруднит, то хотелось бы увидеть какой-то элементарный пример. И еще не пойму, почему разные хешкоды в коде

using System;
class a
{
    public int x;
    public a(int y)
    {
        x = y;
    }
}
class b
{
    static void Main()
    {
        Console.WriteLine(new a(5).GetHashCode() + " " + new a(5).GetHashCode());
    }
}

Ведь тут написано https://msdn.microsoft.com/ru-ru/library/system.object.gethashcode(v=vs.110).aspx

Для двух одинаковых объектов возвращенные хэш-коды равны

Ответы

▲ 6Принят

Ведь, насколько я понял, хешкод берется из скрытой переменной в объекте, к которой нет доступа.

Так ведь и метод вы переопределяете в своем же классе :). Что-то типа:

class a
{
    public int x;

    public a(int y)
    {
        x = y;
    }

    public override int GetHashCode()
    {
        return x;
    }
}

Есть несколько правил для переопределения GetHashCode(), основные:

  1. Используемая функция должна давать хорошее распределение. Это, строго говоря, зависит от данных, однако часто хорошо подходит подобная функция:
    public override int GetHashCode()
    {
        int hashcode = field1.GetHashCode();
        hashcode = 31 * hashcode + field2.GetHashCode();
        hashcode = 31 * hashcode + field3.GetHashCode();
        // и т.д. для остальный полей
        return hashcode;
    }
  1. Эта функция должна быть быстрой.

  2. GetHashCode() не должен выбрасывать исключения.

  3. В идеале GetHashCode() не должен меняться в течение жизни объекта, т.е. полагаться только на неизменяемые члены класса. На практике этим часто пренебрегают, пока не стрельнет.


Так же не забудьте, что Equals() и GetHashCode() всегда должны идти в паре: переопределили один метод, переопределяйте и другой. И если два объекта равны, то у них должен быть одинаковый хэшкод. Обратное необязательно верно (хэш-функция может вернуть одинаковое дначение для разных объектов).


Что почитать (на английском):

Про правильное переопределение GetHashCode()

Про хэш-функции