GetHashCode() со строковыми клавишами

Привет всем, я читал о наилучшем способе реализации переопределения 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 = <type>.m_next_hash_id++;
  return this.m_hash_code;
}

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

Ответы

Ответ 1

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

private string m_foo;
public override int GetHashCode()
{
    return m_foo.GetHashCode();
}

Ответ 2

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

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

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

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

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

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

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

Функция хеширования должна иметь следующие свойства:

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

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

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

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

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

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

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