Преобразование Object.GetHashCode() в Guid

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

dictionary<int,Guid>.Add(instance.GetHashCode(), myGUID());

Есть ли какие-либо потенциальные проблемы, о которых нужно знать?

ПРИМЕЧАНИЕ

Это НЕ должно сохраняться между запусками выполнения, только такой guid

  • создать объект
  • gethashcode(), связать с новым или старым guid
  • перед завершением работы приложения gethashcode() и руководство по поиску для update() или insert() в механизм сохраняемости, ИСПОЛЬЗУЯ GUID

    единственное предположение состоит в том, что gethashcode() остается согласованным во время работы процесса

    также gethashcode() вызывается для того же типа объекта (производного от окна)

Обновление 2 - вот большая картина

  • создать конечный автомат для хранения информации о пользовательских элементах управления WPF (позже именуемых UC) между запусками
  • типы пользовательских элементов управления могут меняться со временем (добавляться/удаляться)
  • в самом первом запуске нет предыдущего состояния, пользователь взаимодействует с подмножеством UC и изменяет свое состояние, которое необходимо воссоздать при перезапуске приложения.
  • этот моментальный снимок состояния делается, когда приложение нормально завершает работу
  • также может быть несколько экземпляров типа UC
  • при завершении работы каждому экземпляру назначается идентификатор и сохраняется вместе с информацией о типе и состоянии.
  • все эти гиды также хранятся в коллекции
  • при перезапуске для каждого guid создайте объект, сохраните ref/guid, восстановите состояние для каждого экземпляра, чтобы приложение выглядело точно так же, как и раньше
  • пользователь может добавлять или удалять экземпляры/типы UC и иным образом взаимодействовать с системой
  • при выключении состояние снова сохраняется
  • выбор в это время состоит в том, чтобы удалить/удалить все предыдущее состояние и вставить информацию о новом состоянии в слой сохраняемости (sql db)
  • при наблюдении/анализе с течением времени выясняется, что многие экземпляры остаются согласованными/статическими и не меняются, поэтому их состояние не нужно удалять/вставлять снова, поскольку информация о состоянии теперь довольно велика и хранится в нелокальной базе данных.
  • поэтому сохраняется только дельта изменений
  • чтобы вычислить дельту, необходимо отслеживать эталонные времена жизни
  • в настоящее время хранится как List<WeakReference> при запуске
  • при выключении перебирать этот список и фактический UC, присутствующий на экране, добавлять/обновлять/удалять ключи соответственно
  • отправить дельту в постоянство

Надеюсь, из вышеизложенного понятно.

Итак, теперь вопрос: почему бы просто не сохранить HashCode (только для пользовательского управления) вместо WeakReference и исключить проверку нулевой ссылки при повторении по списку.

обновление 3 - спасибо всем, наконец-то собираюсь использовать слабую ссылку


person Kumar    schedule 05.12.2011    source источник


Ответы (5)


Используйте GetHashCode для балансировки хеш-таблицы. Вот для чего это нужно. Не используйте его для каких-либо других целей, для которых он не предназначен; это очень опасно.

person Eric Lippert    schedule 06.12.2011
comment
это, конечно, в документе, просто интересно, можем ли мы повторно использовать это, если это возможно, в очень ограниченной области, где это будет использоваться! - person Kumar; 07.12.2011

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

РЕДАКТИРОВАТЬ: Как уже отмечалось, вы также не должны сохранять хэш-коды между запусками выполнения. Нет никакой гарантии, что они будут стабильными перед перезапусками. Не совсем понятно, что именно вы делаете, но это не похоже на хорошую идею.

РЕДАКТИРОВАТЬ: Хорошо, теперь вы заметили, что это не будет постоянным, так что это хорошее начало, но вы все еще не сталкивались с возможностью коллизий хэш-кода. Почему вы вообще хотите позвонить GetHashCode()? Почему бы просто не добавить ссылку в словарь?

person Jon Skeet    schedule 05.12.2011
comment
Более того, есть ли что-нибудь, гарантирующее, что хеш-коды будут стабильными между разными запусками одного и того же процесса? Я знаю, что их стабильность между версиями фреймворка не гарантируется. - person Roger Lipscombe; 05.12.2011
comment
не добавляя ссылку в dict, чтобы не было утечек памяти, т. е. я не храню ссылки на окна (единственный тип для этого, поэтому нет коллизий), которые не отображаются на экране, но моя коллекция содержит ссылку и поддерживает ее! теперь я мог бы обернуть их в слабую ссылку, чтобы не содержать ссылку на Gethashcode(), но я не понимаю, почему не проще просто использовать gethashcode() - person Kumar; 05.12.2011
comment
@Kumar: Почему это может быть утечка памяти? Если у вас нет ссылки на существующий объект (и вы не переопределили GetHashCode), вы все равно не сможете позже получить значения по ключу. До сих пор совершенно неясно, чего вы пытаетесь достичь. Если бы вы могли намного более точно представить общую картину, мы с большей вероятностью сможем вам помочь. - person Jon Skeet; 05.12.2011
comment
Это будет утечка памяти, так как потенциально окно не на экране / закрыто (и приложение не закрыто), но ссылка на него в моем словаре предотвратит его сбор, нет? обновит вопрос выше с подробностями о более широкой картине - person Kumar; 06.12.2011
comment
@Kumar: слабая ссылка проще, чем getHashCode, потому что два объекта могут иметь одинаковый хэш-код. - person Brian; 06.12.2011
comment
@Kumar: Но я хочу сказать, что если вы не собираетесь позже использовать хэш-код исходного объекта, что вы собираетесь использовать? Вы говорите, что при выключении вы вызовете GetHashCode, а затем поищите что-то в движке постоянства — как бы вы это назвали? - person Jon Skeet; 06.12.2011
comment
@Brian - в целом да, типа Usercontrol только нет - person Kumar; 06.12.2011
comment
@Jon, извините, я не был ясен ранее, да, я беру хэш-код в начале, а также в конце, я также подробно описал сценарий выше, большое спасибо за ваше внимание - person Kumar; 06.12.2011
comment
@Kumar: Но если вы берете хэш-коды разных объектов, почему вы ожидаете, что хэш-коды будут одинаковыми? Это ваши собственные типы, в которых вы переопределили GetHashCode? - person Jon Skeet; 06.12.2011
comment
@ Брайан, возможно, но не в том же процессе (или домене приложения?), Возможно, высшие силы могут прокомментировать это - person Kumar; 07.12.2011
comment
@Jon, если предположить, что ваш комментарий был до того, как я обновил Q, но просто для уточнения, я ожидаю, что хэш-код () для производных типов пользовательского управления останется статическим! и нет, я не переопределял их! - person Kumar; 07.12.2011
comment
@Kumar: до сих пор непонятно, что ты имеешь в виду. Ожидаете ли вы, что хэш-код для определенного типа будет постоянным, без переопределения? Вы читали сообщение в блоге Эрика, на которое я ссылаюсь? Я думаю, что вы принципиально не понимаете, что делают хэш-коды и как они работают. - person Jon Skeet; 07.12.2011

Быстрое и простое решение кажется

var dict = new Dictionary<InstanceType, Guid>();
dict.Add(instance, myGUID());

Конечно, вам нужно правильно реализовать InstanceType.Equals, если это еще не так. (Или реализовать IEQuatable<InstanceType>)

person sehe    schedule 05.12.2011
comment
Это правильный способ сделать это. Однако, основываясь на комментариях ОП к ответу Джона, я думаю, что он захочет использовать WeakReference вместо InstanceType. - person Brian; 06.12.2011

Возможные проблемы, о которых я могу думать:

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

Примечание. Джон сказал это более элегантно (см. выше)

person Cᴏʀʏ    schedule 05.12.2011
comment
обновленные запросы, gethashcode() вызывается для того же типа объекта - person Kumar; 05.12.2011

Поскольку это для элементов управления WPF, почему бы просто не добавить Guid в качестве свойства зависимостей? Кажется, вы уже перебираете пользовательские элементы управления, чтобы получить их хэш-коды, так что это, вероятно, будет более простым методом.

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

person The Grand User    schedule 06.12.2011