Общие рекомендации и инструкции по тому, как правильно переопределить объект. GetHashCode ()

В универсальном смысле "рычаг" - что-то, что будет позволять Вам, программисту, просматривать и/или взаимодействовать с и/или изменять что-то, на что это уже идет в системе/программе.

, Например, CMS Drupal предоставляет разработчикам рычаги, которые позволяют им принять дополнительные меры после того, как "узел содержания" создается. Если разработчик не реализует рычаг, узел создается на нормальный. Если разработчик реализует рычаг, у них может быть некоторый дополнительный код, выполненный каждый раз, когда узел создается. Этот код мог сделать что-либо, включая откат и/или изменение первоначального иска. Это могло также сделать что-то несвязанное с созданием узла полностью.

обратный вызов А мог считаться определенным видом рычага. Путем реализации функциональности обратного вызова в систему та система позволяет Вам назвать некоторый дополнительный код после того, как действие завершилось. Однако сцепление (как общее обозначение) не ограничено обратными вызовами.

Другой пример. Иногда Веб-разработчики будут обращаться к именам классов и/или идентификаторам на элементах как рычаги. Поэтому путем размещения идентификатора/имени класса в элемент, они могут тогда использовать JavaScript для изменения того элемента, или "рычага в" к документу страницы. (это расширяет значение, но это является наиболее часто используемым и стоит упомянуть)

44
задан 6 revs, 2 users 100% 26 March 2016 в 17:29
поделиться

9 ответов

Оглавление


Вещи, которые я хотел бы осветить, но еще не затронул:

  • Как создать целое число (Как «преобразовать» объект в int было не очень в любом случае очевидно для меня)
  • На каких полях строится хэш-код.
    • Если это должно быть только в неизменяемых полях, что, если есть только изменяемые поля?
  • Как сгенерировать хорошее случайное распределение. (Свойство MSDN # 3)
    • Часть этого, кажется, выбирает хорошее магическое простое число (мы видели, что использовались 17, 23 и 397), но как вы его выбираете и для чего именно?
  • Как убедиться, что хэш код остается неизменным на протяжении всего времени существования объекта. (Свойство MSDN # 2)
    • Особенно, когда равенство основано на изменяемых полях. (Свойство MSDN №1)
  • Как работать с полями сложных типов (не среди встроенных типов C # ).
    • Сложные объекты и структуры, массивы, коллекции, списки, словари, универсальные типы и т. Д.
    • Например, даже если список или словарь могут быть доступны только для чтения, это не означает, что их содержимое доступно.
  • ] Как работать с унаследованными классами.
    • Должны ли вы каким-то образом включить base.GetHashCode () в свой хеш-код?
  • Не могли бы вы технически просто полениться и вернуть 0? Это сильно нарушило бы рекомендацию № 3 MSDN, но, по крайней мере, удостоверилось бы, что № 1 и № 2 всегда были верны: P
  • Распространенные ошибки и ошибки.
9
ответ дан 26 November 2019 в 22:21
поделиться

Что это за магические числа, часто встречающиеся в реализациях GetHashCode?

Это простые числа. Простые числа используются для создания хэш-кодов, потому что простое число максимизирует использование пространства хэш-кода.

В частности, начните с малого простого числа 3 и учитывайте только младшие полубайты результатов :

  • 3 * 1 = 3 = 3 (мод. 8) = 0011
  • 3 * 2 = 6 = 6 (мод. 8) = 1010
  • 3 * 3 = 9 = 1 ( mod 8) = 0001
  • 3 * 4 = 12 = 4 (mod 8) = 1000
  • 3 * 5 = 15 = 7 (mod 8) = 1111
  • 3 * 6 = 18 = 2 (мод. 8) = 0010
  • 3 * 7 = 21 = 5 (мод. 8) = 1001
  • 3 * 8 = 24 = 0 (мод. 8) = 0000
  • 3 * 9 = 27 = 3 (mod 8) = 0011

И мы начинаем заново. Но ты' Вы заметите, что последовательные числа, кратные нашему простому числу, генерировали все возможные перестановки битов в нашем полубайде, прежде чем начать повторение. Мы можем получить тот же эффект с любым простым числом и любым количеством битов, что делает простые числа оптимальными для генерации почти случайных хэш-кодов. Причина, по которой мы обычно видим большие простые числа вместо маленьких простых чисел, таких как 3 в приведенном выше примере, заключается в том, что для большего количества бит в нашем хэш-коде результаты, полученные от использования малого простого числа, даже не являются псевдослучайными - они просто возрастающая последовательность, пока не произойдет переполнение. Для оптимальной случайности следует использовать простое число, которое приводит к переполнению для довольно малых коэффициентов, если вы не можете гарантировать, что ваши коэффициенты не будут маленькими.

Ссылки по теме:

7
ответ дан 26 November 2019 в 22:21
поделиться

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

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


public override int GetHashCode()
{
    int mc = //magic constant, usually some prime
    return mc * prop1.GetHashCode() * prop2.GetHashCode * ... * propN.GetHashCode();
}

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

Вы можете вернуть одно и то же значение для всех экземпляров, хотя это сделает любые алгоритмы, использующие хеширование (например, словари), очень медленными - по сути, все экземпляры будут хешированы в одно и то же bucket и поиск тогда станут O (n) вместо ожидаемого O (1). Это, конечно, сводит на нет все преимущества использования таких структур для поиска.


public override int GetHashCode()
{
    int mc = //magic constant, usually some prime
    return mc * prop1.GetHashCode() * prop2.GetHashCode * ... * propN.GetHashCode();
}

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

Вы можете вернуть одно и то же значение для всех экземпляров, хотя это сделает любые алгоритмы, использующие хеширование (например, словари), очень медленными - по существу, все экземпляры будут хешированы в одно и то же bucket и поиск тогда станут O (n) вместо ожидаемого O (1). Это, конечно, сводит на нет все преимущества использования таких структур для поиска.


public override int GetHashCode()
{
    int mc = //magic constant, usually some prime
    return mc * prop1.GetHashCode() * prop2.GetHashCode * ... * propN.GetHashCode();
}

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

Вы можете вернуть одно и то же значение для всех экземпляров, хотя это сделает любые алгоритмы, использующие хеширование (например, словари), очень медленными - по сути, все экземпляры будут хешированы в одно и то же bucket и поиск тогда станут O (n) вместо ожидаемого O (1). Это, конечно, сводит на нет все преимущества использования таких структур для поиска.

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

Вы можете вернуть одно и то же значение для всех экземпляров, хотя это сделает любые алгоритмы, использующие хеширование (например, словари), очень медленными - по существу, все экземпляры будут хешированы в одно и то же bucket и поиск тогда станут O (n) вместо ожидаемого O (1). Это, конечно, сводит на нет все преимущества использования таких структур для поиска.

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

Вы можете вернуть одно и то же значение для всех экземпляров, хотя это сделает любые алгоритмы, использующие хеширование (например, словари), очень медленными - по существу, все экземпляры будут хешированы в одно и то же bucket и поиск тогда станут O (n) вместо ожидаемого O (1). Это, конечно, сводит на нет любые преимущества использования таких структур для поиска.

что приемлемо, учитывая определение № 2 в вашем вопросе. Он также работает со всеми типами единообразно.

Вы можете вернуть одно и то же значение для всех экземпляров, хотя это сделает любые алгоритмы, использующие хеширование (например, словари), очень медленными - по сути, все экземпляры будут хешированы в одно и то же bucket и поиск тогда станут O (n) вместо ожидаемого O (1). Это, конечно, сводит на нет все преимущества использования таких структур для поиска.

что приемлемо, учитывая определение № 2 в вашем вопросе. Он также работает со всеми типами единообразно.

Вы можете вернуть одно и то же значение для всех экземпляров, хотя это сделает любые алгоритмы, использующие хеширование (например, словари), очень медленными - по сути, все экземпляры будут хешированы в одно и то же bucket и поиск тогда станут O (n) вместо ожидаемого O (1). Это, конечно, сводит на нет любые преимущества использования таких структур для поиска.

2
ответ дан 26 November 2019 в 22:21
поделиться

Когда я переопределяю объект . ; в противном случае Hashtable может работать неправильно.

Ссылки по теме:

0
ответ дан 26 November 2019 в 22:21
поделиться

Why do I have to override object.GetHashCode()?

Overriding this method is important because the following property must always remain true:

If two objects compare as equal, the GetHashCode method for each object must return the same value.

The reason, as stated by JaredPar in a blog post on implementing equality, is that

Many classes use the hash code to classify an object. In particular hash tables and dictionaries tend to place objects in buckets based on their hash code. When checking if an object is already in the hash table it will first look for it in a bucket. If two objects are equal but have different hash codes they may be put into different buckets and the dictionary would fail to lookup the object.

Related links:

2
ответ дан 26 November 2019 в 22:21
поделиться
public override int GetHashCode()
{
    return IntProp1 ^ IntProp2 ^ StrProp3.GetHashCode() ^ StrProp4.GetHashCode ^ CustomClassProp.GetHashCode;
}

Сделайте то же самое в методе customClass GetHasCode . Работает как шарм.

-2
ответ дан 26 November 2019 в 22:21
поделиться

На каких полях следует основывать хэш-код? Если она должна быть только на неизменяемых полях, то что если есть только изменяемые?

Она не должна основываться только на неизменяемых полях. Я бы основывал его на полях, которые определяют результат метода равенства.

-121--1134617-

Есть ли что-то вроде приложения global onPause () и onResume ()?

Нет, извините.

Основное действие прослушивает GPS исправления, которые я хочу продолжить работа при переходе на другой экран/активность. Поэтому я не могу отменить регистрацию моего LocationListener в действие onPause (). Однако я все еще хотите отменить регистрацию прослушивателя GPS при переключении на другое приложение (так что сэкономьте аккумулятор) и поверните его назад при возврате в мое приложение, независимо от того, какой экран/действие пользователь в данный момент.

Вот один возможный подход:

Шаг # 1: Переместите логику LocationListener в службу Service , к которой действия подключаются через локальную привязку образца или что-то подобное. Также есть по крайней мере один вызов службы startService () , поэтому unbindService () не приведет к удалению Service (при условии, что используется локальный образец привязки).

Шаг # 2: действия вызываются в службу во время onPause () и onResume () .

Шаг # 3: выполните ведение ссылочного количества незавершенных операций.

Шаг # 4: Когда число ссылок достигнет нуля, служба должна быть упорядочена для пробуждения через таймер и TimerTask . Кроме того, отмените любое такое ожидающее TimerTask , если число ссылок увеличивается.

Шаг # 5: отключите GPS TimerTask , если он когда-либо будет выполнен.

Сетка заключается в том, что Вы освобождаете GPS только после такого количества бездействия. Это бездействие может быть по любой причине.

-121--2409118-

Как убедиться, что хэш-код остается одинаковым в течение всего срока существования объекта. (Свойство MSDN # 2) Особенно, когда равенство основано на изменяемых полях. (Свойство MSDN # 1)

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

0
ответ дан 26 November 2019 в 22:21
поделиться

Другие ответы являются точечными. Однако я бы также упомянул, что существуют два различных «стиля» системы управления версиями:
1) централизованно = вы сохраняете код на сервере, хотя это может быть ваша локальная машина (например, CVS, SVN)
2) distributed = вы сохраняете свой код в локальной базе данных (например, Git, Mercurial)

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

-121--3030633-

См. RFC2616 - Протокол передачи гипертекста - HTTP/1.1 , раздел 4,3 «Тело сообщения»:

Тело сообщения НЕ ДОЛЖНО БЫТЬ ВКЛЮЧЕНО в запрос, если спецификация метода запроса (раздел 5,1,1) не позволяет отправлять тело объекта в запросах.

В разделе 9,3 «GET», включая объект-тело, не запрещается.

Таким образом, да, вы можете отправить объект-тело с запросом HTTP GET.

-121--2151532-

На каких полях будет основан хэш-код? Если он должен быть только на неизменяемых полях, то что если есть только изменяемые поля?

Я бы основывал его на полях, которые определяют результат метода равенства.

0
ответ дан 26 November 2019 в 22:21
поделиться

A) Вы должны переопределить Equals и GetHashCode, если вы хотите использовать равенство значений вместо ссылочного равенства по умолчанию. . В последнем случае две объектные ссылки сравниваются как равные, если они обе относятся к одному и тому же экземпляру объекта. С первым они сравниваются как равные, если их значение одинаково, даже если они относятся к разным объектам. Например, вы, вероятно, захотите использовать равенство значений для объектов Date, Money и Point.

B) Чтобы реализовать равенство значений, вы должны переопределить Equals и GetHashCode. Оба должны зависеть от полей объекта, которые инкапсулируют значение. Например, Date.Year, Date.Month и Date.Day; или Money.Currency и Money.Amount; или Point.X, Point.Y и Point.Z. Вам также следует рассмотреть возможность переопределения operator ==, operator! =, Operator <и operator>.

C) Хэш-код не должен оставаться постоянным на протяжении всего времени существования объекта. Однако он должен оставаться неизменным, пока участвует в качестве ключа в хэше. Из документа MSDN для словаря: «Пока объект используется в качестве ключа в Dictionary <(Of <(TKey, TValue>)>), он не должен изменяться каким-либо образом, влияющим на его хеш-значение». Если необходимо изменить значение ключа, удалите запись из словаря, измените значение ключа и замените запись.

D) ИМО, вы упростите себе жизнь, если ваши объекты ценностей сами по себе неизменны.

2
ответ дан 26 November 2019 в 22:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: