Я знаю, я знаю, много вопросов о хеш-кодах, но я хотел бы получить мнение о нескольких решениях для вычисления хэш-кода для изменяемых объектов.По-прежнему на хэш-коды изменчивых объектов
Исходя из этого предположения (documentation):
В общем, для изменяемых ссылочных типов, вы должны переопределить GetHashCode только если:
- Вы можете вычислить хэш-код из полей, которые не являются изменчивый; или
- Вы можете гарантировать, что хеш-код изменяемого объекта не изменяется, пока объект содержится в коллекции, которая полагается на свой хэш-код.
В противном случае вы можете подумать, что измененный объект потерян в хэш-таблице.
Какой лучший вариант, когда мне нужно сохранить изменяемый объект в хеш-таблицу?
РЕШЕНИЕ 1
Игнорировать проблему. Подсчитайте, если с одним из доступных алгоритмов (здесь и, например, для гео координат в C#):
public override Int32 GetHashCode() {
Int32 n1 = 99999997;
Int32 hash_lat = this.Latitude.GetHashCode() % n1;
Int32 hash_lng = this.Longitude.GetHashCode();
_final_hashcode = (((hash_lat << 5) + hash_lat)^hash_lng);
return _final_hashcode.Value;
}
РЕШЕНИЕ 2
Вычислить его в первый раз на изменяемых значений и хранить его в очередной раз :
private Int32? _final_hashcode = null;
public override Int32 GetHashCode() {
// hash code must not change when lat and lng does change
if (_final_hashcode == null) {
Int32 n1 = 99999997;
Int32 hash_lat = this.Latitude.GetHashCode() % n1;
Int32 hash_lng = this.Longitude.GetHashCode();
_final_hashcode = (((hash_lat << 5) + hash_lat)^hash_lng);
}
return _final_hashcode.Value;
}
РЕШЕНИЕ 3
Добавить закрытый неизменный ключ для объекта, который будет использоваться только для хэш-кода. Таким образом, когда изменяемые поля изменяются, хеш-код не изменяется.
Вот пример с использованием случайного сгенерированного частного GUID, который не требуется для класса и используется только для хэш-кода:
public class GeoPosition {
private const Guid _guidForHash = Guid.NewGuid(); // init during contruction
public override Int32 GetHashCode() {
return _guidForHash.GetHashCode();
}
// mutable properties here and other stuff
// ...
}
Что вы думаете?
Я не знаю всех соответствующих критериев в суждении между решениями, - но третий делает меня чище, даже если у него немного накладных расходов. –
Это звучит как XY-проблема для меня. У всех ваших решений есть проблемы. Для решения 1 это очевидно (вы сами написали). Для решений 2 и 3 два объекта, которые имеют одни и те же данные, могут приводить к различным хэш-кодам, в зависимости от того, когда сначала был вычислен хэш-код. Итак: вам нужно лучше описать, что такое ваша проблема _real_. –
@ThomasMueller Вы правы. Во всяком случае, где вы получили информацию о том, что проблема с двумя объектами, имеющими одни и те же данные, и разные хэш-коды? Является ли требование вычисления хэш-кода, или что? –