Вопрос

Я пытаюсь понять роль метода GethashCode интерфейса IEQUATIONAMERER.

В следующем примере взяты из MSDN:

using System;
using System.Collections.Generic;
class Example {
    static void Main() {
        try {

            BoxEqualityComparer boxEqC = new BoxEqualityComparer();

            Dictionary<Box, String> boxes = new Dictionary<Box,
                                                string>(boxEqC);

            Box redBox = new Box(4, 3, 4);
            Box blueBox = new Box(4, 3, 4);

            boxes.Add(redBox, "red");
            boxes.Add(blueBox, "blue");

            Console.WriteLine(redBox.GetHashCode());
            Console.WriteLine(blueBox.GetHashCode());
        }
        catch (ArgumentException argEx) {

            Console.WriteLine(argEx.Message);
        }
    }
}

public class Box {
    public Box(int h, int l, int w) {
        this.Height = h;
        this.Length = l;
        this.Width = w;
    }
    public int Height { get; set; }
    public int Length { get; set; }
    public int Width { get; set; }
}

class BoxEqualityComparer : IEqualityComparer<Box> {

    public bool Equals(Box b1, Box b2) {
        if (b1.Height == b2.Height & b1.Length == b2.Length
                            & b1.Width == b2.Width) {
            return true;
        }
        else {
            return false;
        }
    }

    public int GetHashCode(Box bx) {
        int hCode = bx.Height ^ bx.Length ^ bx.Width;
        return hCode.GetHashCode();
    }
}

Разве не должно быть достаточно реализации метода метода для сравнения двух полевых объектов? Именно здесь мы говорим, что правило используется для сравнения объектов. Почему нужен GethashCode?

Спасибо.

Лювии

Это было полезно?

Решение

Немного фона сначала ...

Каждый объект в .NET имеет метод равенства и метод GetHashCode.

Метод равенства используется для сравнения одного объекта с другим объектом - посмотреть, являются ли двумя объектами эквивалентными.

Метод GetHashCode генерирует 32-разное целое представление объекта. Поскольку нет предела, сколько информации может содержать объект, некоторые хеш-коды совместно используются несколькими объектами - поэтому хеш-код не обязательно уникален.

Словарь - это действительно прохладная структура данных, которая торгует более высокой след памяти в возвращении для (более или менее) постоянных затрат на добавление / удаление / получение операций. Это плохой выбор для итерации, хотя. Внутренне, словарь содержит массив ведер, где можно сохранить значения. Когда вы добавляете ключ и значение в словарь, метод GetHashCode вызывается на ключ. Возвращенный Hashcode используется для определения индекса ведра, в котором следует хранить пару ключ / значение.

Когда вы хотите получить доступ к значению, вы переходите в ключ снова. Метод GetHashCode вызывается на клавише, а ведро, содержащее значение, расположено.

Когда IequalityComparer передается в конструктор словаря, iequalityComparer.equals и IequalityComparer.gethashCode Методы используются вместо методов на ключевых объектах.

Теперь, чтобы объяснить, почему оба метода необходимы, рассмотрим этот пример:

BoxEqualityComparer boxEqC = new BoxEqualityComparer(); 

Dictionary<Box, String> boxes = new Dictionary<Box, string>(boxEqC); 

Box redBox = new Box(100, 100, 25);
Box blueBox = new Box(1000, 1000, 25);

boxes.Add(redBox, "red"); 
boxes.Add(blueBox, "blue"); 

Используя метод BoxequalityComperer.gethashCode В вашем примере, оба этих коробки имеют одинаковый хе хе хе хе хе хе хе хе хе хе хе хе хе хе хе хе хе хе хе хе хе хе хе хе хехкодов - 1000 ^ 100 ^ 25 = 1000 ^ 1000 ^ 25 = 25 - хотя они явно не один и тот же объект. Причина, по которой они такие же HASHCODE в этом случае, заключается в том, что вы используете оператор ^ (побитовой эксклюзив или) так 100 ^ 100, оставив ноль, как и 1000 ^ 1000. Когда два разных объекта имеют один и тот же ключ, мы называем то, что столкновение.

Когда мы добавляем две пары клавиш / значений с тем же Hashcode в словаре, они оба хранятся в том же ведре. Таким образом, когда мы хотим получить значение, метод GetHashCode вызывается на нашем клавише, чтобы найти ведро. Поскольку в ведре более одного значения есть более одного значения, словарь, итасившими на всех парах ключа / значения в ведре, вызывающем метод равенства на клавишах, чтобы найти правильный.

В примере, который вы разместили, две коробки эквивалентны, поэтому метод равенства возвращает True. В этом случае словарь имеет две одинаковые ключи, поэтому бросает исключение.

TLDR

Таким образом, таким образом, метод GetHashCode используется для генерации адреса, в котором хранится объект. Так что словарь не должен искать его. Он просто вычисляет Hashcode и прыгает в это место. Метод равенства является лучшим испытанием равенства, но не может использоваться для отображения объекта в адресное пространство.

надеюсь, это поможет

Другие советы

Gethashcode. Используется в словаре под клювлениям, и он создает хеш для хранения объектов в нем. Вот хорошая статья, почему и как использовать Iequaltycomparer и Gethashcode. http://dotnetperls.com/iequalityComparer

В то время как это будет возможно для Dictionary<TKey,TValue> иметь его GetValue и аналогичные методы вызова Equals На каждом одном хранимом клавише, чтобы увидеть, соответствует ли он одному, которое нужно было бы очень медленно. Вместо этого, как и многие хэш-коллекции, это опирается на GetHashCode Быстро исключить большинство не совпадающих ценностей от рассмотрения. Если звонить GetHashCode По искам товара доходятся 42, а коллекция имеет 53,917 предметов, но призывает GetHashCode На 53,914 пункта давали значение, отличное от 42, то только 3 предмета должны будут сравнивать с теми, которые требуются. Другой 53,914 может безопасно игнорировать.

Причина А. GetHashCode включен в IEqualityComparer<T> состоит в том, чтобы позволить возможность того, что потребитель словаря может захотеть рассматривать как равные объекты, которые обычно нет рассматривать друг друга как равное. Наиболее распространенным примером является абонентом, который хочет использовать строки в качестве клавиш, но используют сравнения нечувствительности к регистру. Чтобы сделать эту работу эффективно, в словаре необходимо иметь некоторую форму хэш-функции, которая даст то же значение для «Фокса» и «Фокс», но, надеюсь, уступит что-то еще для «коробки» или «зебра». Поскольку GetHashCode метод встроен в String Не работает так, что словарь нужно будет получить такой метод откуда-то еще, и IEqualityComparer<T> является наиболее логичным местом, поскольку необходимость такого хэш-кода будет очень сильно связана с Equals Метод, который считает «лиса» и «лису», идентично друг другу, но не «коробку» или «зебру».

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top