GetHashCode () со строковыми ключами - PullRequest
14 голосов
/ 23 июля 2010

Привет всем, я читал о лучшем способе реализации переопределения GetHashCode () для объектов в .NET, и большинство ответов, которые я получаю, связаны с каким-то объединением чисел из членов, которые представляют числовые типыметод.Проблема в том, что у меня есть объект, который использует буквенно-цифровую строку в качестве ключа, и мне интересно, есть ли какая-то принципиальная ошибка с использованием внутреннего идентификатора для объектов со строками в качестве ключей, что-то вроде следующего?


// Override GetHashCode() to return a permanent, unique identifier for
// this object.
static private int m_next_hash_id = 1;
private int m_hash_code = 0;
public override int GetHashCode() {
  if (this.m_hash_code == 0)
    this.m_hash_code = <<i>type</i>>.m_next_hash_id++;
  return this.m_hash_code;
}

Есть ли лучший способ придумать уникальный хеш-код для объекта, который использует буквенно-цифровую строку в качестве ключа?(И нет, числовые части буквенно-цифровой строки не уникальны; некоторые из этих строк вообще не содержат цифр.) Любые мысли приветствуются!

Ответы [ 5 ]

22 голосов
/ 23 июля 2010

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

private string m_foo;
public override int GetHashCode()
{
    return m_foo.GetHashCode();
}
21 голосов
/ 23 июля 2010

Это плохой шаблон для генерации хешей для объекта.

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

Если вы просто сгенерируете случайное значение и назовете его хеш-кодом, у вас не будет повторяемости. Другой экземпляр с такими же ключевыми полями будет иметь другой хеш-код и будет нарушать поведение, ожидаемое такими классами, как HashSet, Dictionary и т. Д.

Если у вас уже есть идентифицирующий строковый член в вашем объекте, просто верните его хеш-код.

Документация на MSDN для разработчиков GetHashCode() является обязательной для чтения для всех, кто планирует переопределить этот метод:

Примечания для разработчиков

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

Хеш-функция должна иметь следующие свойства:

Если два объекта сравниваются как равные, Метод GetHashCode для каждого объекта должен вернуть то же значение. Тем не мение, если два объекта не сравниваются как равны, методы GetHashCode для два объекта не должны возвращаться разные значения.

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

Для лучшей производительности, хеш функция должна генерировать случайный Распределение для всего ввода.

Например, реализация Метод GetHashCode, предоставляемый Класс String возвращает идентичный хеш коды для одинаковых строковых значений. Поэтому два объекта String возвращают тот же хэш-код, если они представляют то же самое строковое значение. Так же Метод использует все символы в строка для генерации случайным образом распределенный вывод, даже когда вход сгруппирован в определенных диапазонах (например, многие пользователи могут иметь строки, содержащие только нижнюю 128 символов ASCII, даже если Строка может содержать любой из 65 535 Символы Юникода).

2 голосов
/ 23 июля 2010

Хеш-коды не должны быть уникальными. При условии, что ваша реализация Equals верна, можно возвращать один и тот же хэш-код для двух экземпляров. Логика m_next_hash_id нарушена, поскольку она позволяет двум объектам иметь разные хеш-коды, даже если они сравниваются равными.

MSDN дает хороший набор инструкций о том, как реализовать Equals и GetHashCode. Несколько примеров здесь реализуют GetHashCode в терминах хэш-кодов полей объекта

0 голосов
/ 23 июля 2010

Я полагаю, что вы обычно хотите, чтобы GetHashCode() возвращал что-то, что идентифицирует объект по его значению, а не по его экземпляру. Если я понимаю идею здесь, я думаю, ваш метод обеспечит GetHashCode() для двух разных объектовэквивалентные значения будут возвращать разные хэши только потому, что они являются разными экземплярами.

GetHashCode() предназначен для возврата значения, которое позволяет сравнивать значения двух объектов, а не их ссылок.

0 голосов
/ 23 июля 2010

Да, лучшим способом было бы использовать хеш-код строки, которая у вас уже есть.Если буквенно-цифровая строка определяет идентичность вашего объекта, ее хеш-код очень хорошо подойдет для хэш-кода вашего объекта.

Идея увеличения статического поля и использования его в качестве хэш-кода плохаяодин.Хеш-код должен иметь равномерное распределение по пространству возможных значений.Это, среди прочего, гарантирует, что он будет хорошо работать при использовании в качестве ключа в хеш-таблице.

...