Сравнение строковых хэшей на разных машинах - PullRequest
0 голосов
/ 22 января 2019
  • У меня есть несколько идентификаторов в виде строки, например "enemy1", "enemy2".
  • Я хочу сохранить прогресс, зависит от того, сколько из каждого врага я убил. Для этой цели я использую словарь типа { { "enemy1", 0 }, { "enemy2", 1 } }.
  • Затем я хочу разделить сохранение проигрывателя между несколькими компьютерами, на которых он может играть (например, ПК и ноутбук) через сеть (сначала сериализовать его в файл JSON). Для уменьшения размера и увеличения производительности я использую хеш вместо полной строки, используя этот alg (потому что MDSN сказал, что по умолчанию хэш alg может отличаться на разных машинах):
int hash_ = 0;
public override int GetHashCode()
    {
        if(hash_ == 0)
        { 
          hash_ = 5381;
          foreach(var ch in id_)
            hash_ = ((hash_ << 5) + hash_) ^ ch;
        }
        return hash_;
    }

Итак, вопрос в том, что alg в C # будет возвращать те же результаты, которые использует любой игрок машины.


UPD: в комментариях отмечу, что основная часть вопроса была неясной. Так. Если я могу гарантировать, что все файлы перед десериализацией будут в одной и той же кодировке, будет ли одинаковое представление char на каждой машине, которую может использовать плеер, и операция ^ ch даст одинаковый результат? Я имею в виду WinX64 / WinX32 / Mac / Linux / ... машины

1 Ответ

0 голосов
/ 22 января 2019

Да, этот код даст одинаковый результат на каждой платформе для одного и того же ввода. char - это кодовая единица UTF-16, независимо от платформы, и любой заданный char будет преобразован в одно и то же значение int на каждой платформе. Как обычно с хеш-кодами, вычисляемыми так, вы не должны предполагать, что равные хеш-коды подразумевают равные исходные значения. (Если честно, неясно, как вы собираетесь использовать хеш.)

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

...