2009-10-14 1 views
2

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

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

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

Я знаю, что документация .Net позволяет реализовать хэш-коды между версиями каркаса .Net для изменения (и между 32 и 64-разрядными версиями), но я не изменил версию фреймворка и не было никакой инфраструктуры Обновления в последнее время, насколько я помню

Любые идеи, потому что это кажется действительно странным?

Редактировать

Хэш-коды генерируются, как следует:

//Compute Hash Code 
this._hashcode = 
    (this._nodetype + this.ToString() + PlainLiteralHashCodeSalt).GetHashCode(); 
+0

как кажется немного легким только как комментарий: объект переместился в другое пространство имен, и вы берете полное имя объекта для своего хэша. Тогда вам не придется прикасаться к коду, а только перемещать объект. – StampedeXV

+0

строковое представление не основано на имени типа, а на строчном представлении значения объекта – RobV

+0

также я проверил SVN, и все файлы для типов, у которых есть пользовательские хеш-коды, ** ** ** вообще не изменены – RobV

ответ

3

Что StampedeXV предлагает в своем комментарии, так как Object.ToString() вернет полное имя по умолчанию, если ToString() не является избыточным.

  1. Изменение пространства имен (или имени класса) изменит это значение, если ToString() не переопределяется.
  2. Очевидно, что переопределение ToString() изменит его.
  3. Проверьте, как и где находится _nodeType.
  4. PlainLiteralHashCodeSalt остается мистерией (я полагаю, это постоянная строка).
  5. Никто не гарантирует, что String.HashCode() не изменится, поэтому вы можете хотя бы использовать Reflector, чтобы получить источник методов и включить его в свою библиотеку. Это не что-то, что я обычно рекомендую, но вы не хотите зависеть от этого в будущем.

Излишне говорить, что вы должны отслеживать все 3 значения (_nodeType, this.ToString() и сольную строку), чтобы проверить, что они не изменились. Если вы можете вернуться к более старой версии, которая работает, вы на полпути.

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

Но поскольку он уже находится в базе данных, ваша главная проблема заключается в том, как вернуть реализацию HashCode.

+0

Это связано с производительностью, и я знаю риски, связанные с этим, но в сочетании с другими аспектами подхода настойчивости он делает значительный порядок величин в разнице в производительности. Тип узла назначается один раз в базовом конструкторе, PlainLiteralHashCodeSalt является константой строки – RobV

+0

Принял ответ, потому что, глядя на вещи, я понял, что проблема в том, что я использовал старую базу данных, которая была заполнена до моего изменения в генерации хеш-кода (который было пару месяцев назад), поэтому коды хэша оказались недействительными, т. е. значения, используемые для этих трех вещей, были разными в то время (попадание на стол) – RobV

1

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

Смежные вопросы