СЕКРЕТЫ И УЛОВКИ
Когда String.GetHashCode() в .NET C# сводит вас с ума
Знайте, когда следует зависеть от String.GetHashCode() в .NET C#, а когда нет.
История
Я работал над побочным проектом инструмента, который помогал мне в моей повседневной работе. В одном модуле мне нужно было отслеживать некоторые транзакции, которые могли выполняться между запусками инструмента. Другими словами, когда я закрываю и открываю инструмент, эти транзакции должны быть там.
Для хранения я использовал базу данных SQLite, в которой я сохраняю хэш-код сущности, представляющей мой класс транзакций. Я зависел от этого хэш-кода, так как в какой-то момент инструмент сгенерировал новый хэш-код и сравнил его с уже сохраненным в базе данных.
Итак, установив все на свои места, я запустил инструмент, попробуйте, да… он работает. Я закрываю инструмент, делаю кое-что, затем пытаюсь протестировать что-то другое, теперь оно не работает должным образом!!
Я пытался понять, что происходит, и, наконец, понял. Сравнение хэш-кода не работает нормально. Во время одного и того же сеанса работы инструмента сравнение работает нормально. Однако, когда я закрываю и открываю инструмент, вновь сгенерированный хэш-код для той же самой транзакции не совпадает с сохраненным в базе данных.
Я поискал в интернете и обнаружил, что это правда. По данным Майкрософт:
Стабильность самого хэш-кода не гарантируется. Хэш-коды для идентичных строк могут различаться в разных реализациях .NET, в разных версиях .NET и на разных платформах .NET (например, 32-разрядных и 64-разрядных) для одной версии .NET. В некоторых случаях они могут даже различаться доменом приложения. Это означает, что два последующих запуска одной и той же программы могут возвращать разные хэш-коды.
В результате хэш-коды никогда не должны использоваться за пределами домена приложения, в котором они были созданы, их никогда нельзя использовать в качестве ключевых полей в коллекции, и их никогда не следует сохранять.
Наконец, не используйте хэш-код вместо значения, возвращаемого криптографической функцией хэширования, если вам нужен криптографически стойкий хэш. Для криптографических хэшей используйте класс, производный от класса System.Security.Cryptography.HashAlgorithm или System.Security.Cryptography.KeyedHashAlgorithm.
Для получения дополнительной информации о хеш-кодах см. Object.GetHashCode.
Поэтому сейчас я делюсь этим с вами и собираюсь рассказать вам, как по-хорошему преодолеть это.
Давайте попробуем
Создайте консольное приложение со следующим кодом.
Простой класс Employee
с простой реализацией интерфейса IEquatable<Employee>
.
Просто обратите внимание, как реализован метод GetHashCode
.
При запуске приложения получаем вот что:
Теперь остановите приложение и запустите его снова. Вот что мы получаем:
Видите, оба результата не совпадают.
Правильный способ исправить это
Компаратор ArrayEqualityComparer‹T›
StringExtensions
ФиксированныйСотрудник
При запуске приложения получаем вот что:
Теперь остановите приложение и запустите его снова. Вот что мы получаем:
Видите, оба результата одинаковы.
Краткое содержание
Если вам нужно, чтобы результат String.GetHashCode()
сохранялся между сеансами запуска вашего приложения, вам нужно будет следовать этому или другому подобному пути. В противном случае вы будете получать новый результат каждый раз, когда останавливаете и запускаете приложение.
Вот и все, надеюсь, вам было так же интересно читать эту историю, как мне было ее писать.
Надеюсь, вы нашли этот контент полезным. Если вы хотите поддержать:
▶ Если вы еще не являетесь участником Medium, вы можете использовать мою реферальную ссылку, чтобы я мог получать часть ваших сборов от Medium. > вы ничего не платите.
▶ Подпишитесь на мою рассылку новостей, чтобы получать рекомендации, руководства, подсказки, подсказки и многое другое прямо на ваш почтовый ящик.
Другие источники
Это другие ресурсы, которые могут оказаться полезными.