Переопределение Equals и GetHashCode типа, который имеет «dibs»? - PullRequest
2 голосов
/ 10 апреля 2011

Этот вопрос и ответ Джона заставили меня осознать, что это вообще существует, поэтому я заинтересовался и запустил Visual Studio.


Я последовал одному примеру на странице MSDN, а затем создал свой собственный маленький пример. Это выглядит следующим образом:

public class Person : IEquatable<Person>
{
    public string IdNumber { get; set; }
    public string Name { get; set; }

    public bool Equals(Person otherPerson)
    {
        if (IdNumber == otherPerson.IdNumber)
            return true;
        else
            return false;
    }

    public override bool Equals(object obj)
    {
        if (obj == null) 
            return base.Equals(obj);

        if (!(obj is Person))
            throw new InvalidCastException("The Object isn't of Type Person.");
        else
            return Equals(obj as Person);
    }

    public override int GetHashCode()
    {
        return IdNumber.GetHashCode();
    }

    public static bool operator ==(Person person1, Person person2)
    {
        return person1.Equals(person2);
    }

    public static bool operator !=(Person person1, Person person2)
    {
        return (!person1.Equals(person2));
    }
}

Итак, у меня есть пара вопросов:

  1. Если метод Equals хорошо справляется с обработкой моего пользовательского равенства, почему я должен также переопределить метод GetHashCode?

  2. При сравнении чего-либо подобного ниже, какой компаратор используется, равно или GetHashCode?

.

static void Main(string[] args)
{
    Person sergio = new Person() { IdNumber = "1", Name = "Sergio" };
    Person lucille = new Person() { IdNumber = "2", Name = "Lucille" };

    List<Person> people = new List<Person>(){
        sergio,
        lucille
    };

    Person lucille2 = new Person() { IdNumber = "2", Name = "Lucille" };
    if (people.Contains(lucille2))
    {
        Console.WriteLine("Already exists.");
    }

    Console.ReadKey();
}
  1. Что именно делает операторный метод? Похоже, там происходит какая-то черная магия вуду.

Ответы [ 4 ]

7 голосов
/ 10 апреля 2011

Если метод Equals хорошо справляется с обработкой моего пользовательского равенства, зачем мне также переопределять метод GetHashCode?

Это позволяет использовать ваш тип в коллекцияхкоторый работает через хеширование, например, является ключом в Dictionary<T, U> или хранится в HashSet<T>.

При сравнении чего-то подобного ниже, какой компаратор используется, Equals или GetHashCode?

GetHashCode не используется для сравнений - только для операций хеширования.Всегда используется равенство.

Что именно делает операторный метод?Похоже, там происходит какая-то черная магия вуду.

Это позволяет вам напрямую использовать == в двух экземплярах вашего типа.Без этого вы будете сравнивать по ссылке, если ваш тип является классом, а не по значениям внутри вашего типа.

3 голосов
/ 10 апреля 2011

Цель GetHashCode - сбалансировать хеш-таблицу , а не определить равенство. При поиске члена хеш-таблицы проверенная область хеша определяется по хеш-коду, а затем определяется равенство объекта в корзине или нет. Вот почему GetHashCode должен согласиться с равенством.

Подробнее см. Мою статью на эту тему:

http://ericlippert.com/2011/02/28/guidelines-and-rules-for-gethashcode/

1 голос
/ 10 апреля 2011

GetHashCode и Equals - это две разные вещи.Equals определяет равенство.GetHashCode возвращает хеш-код, подходящий для хэш-карты, но не гарантирует равенство.Следовательно, в вопросах равенства Equals будет методом, который определяет равенство.

GetHashCode предназначен для хеш-наборов, таких как Dictionary.При поиске элемента в словаре вы будете сопоставлять запись в хеш-коде, затем на Equals.

0 голосов
/ 10 апреля 2011

GetHashCode используется MSDN только при использовании хэш-таблицы.

Если вам нужно равенство, вы заботитесь только о равных. MSDN предлагает также реализовать GetHashCode, потому что рано или поздно вы можете использовать ваши объекты в хеш-подобном объекте (хеш-таблица, хеш-карта и т. Д.).

Представьте, что объекты имеют 1000 байтов, и вам нужен быстрый способ определения равенства между двумя объектами - вы вычисляете ключ хеша (через GetHashCode). Если ключи не совпадают, объекты разные. Если они совпадают, вы не можете точно сказать, действительно ли они равны, вам нужно проверить с помощью Equal () - это дороже.

Коллекции хеш-таблиц используют эту идею.

...