Переопределение Объекта. Равняется () методу экземпляра в C#; теперь Кодируйте Analysis/FxCop предупреждение CA2218: “должен также переопределить GetHashCode”. Я должен подавить это?

У меня есть сложный класс в моем проекте C#, на котором я хочу смочь сделать тесты равенства. Это не тривиальный класс; это содержит множество скалярных свойств, а также ссылок на другие объекты и наборы (например, IDictionary). Если это имеет значение мой класс изолируется.

Для включения оптимизации производительности в другом месте в моей системе (оптимизация, которая избегает дорогостоящего сетевого распространения в прямом и обратном направлениях) я должен смочь сравнить экземпляры этих объектов друг другу для равенства – кроме встроенного ссылочного равенства – и таким образом, я переопределяю Объект. Равняется () методу экземпляра. Однако теперь, когда я сделал это, Анализ кода 2008 Visual Studio иначе. FxCop, который я сохраняю включенным по умолчанию, повышает соблюдающее предупреждение:

предупреждение: CA2218: Microsoft. Использование: Так как 'MySuperDuperClass' переопределяет, Равняется, он должен также переопределить GetHashCode.

Я думаю, что понимаю объяснение для этого предупреждения: Если я собираюсь быть использованием таких объектов как ключ в наборе, хэш-код важен. т.е. посмотрите этот вопрос. Однако я не собираюсь быть использованием этих объектов как ключ в наборе. Когда-либо.

Чувствуя себя выровненным по ширине для подавления предупреждения я искал код CA2218 в документации MSDN для получения полного имени предупреждения, таким образом, я мог применить a SuppressMessage припишите моему классу следующим образом:

    [SuppressMessage("Microsoft.Naming",
        "CA2218:OverrideGetHashCodeOnOverridingEquals",
        Justification="This class is not to be used as key in a hashtable.")]

Однако при чтении далее, я заметил следующее:

Как зафиксировать нарушения

Для фиксации нарушения этого правила обеспечьте реализацию GetHashCode. Для пары объектов того же типа необходимо удостовериться, что реализация возвращает то же значение, если реализация Равняется, возвращает true для пары.

Когда отключить предупреждения

-----> Не подавляют предупреждение от этого правила. [стрелка и шахта акцента]

Так, я хотел бы знать: Почему я не должен подавлять это предупреждение, поскольку я планировал к? Разве мой случай не гарантирует подавление? Я не хочу кодировать реализацию GetHashCode () для этого объекта, который никогда не будут называть, так как мой объект никогда не будет ключом в наборе. Если бы я хотел быть педантичным вместо подавления, то это было бы более разумно, чтобы я переопределил GetHashCode () с реализацией, которая бросает NotImplementedException?


Обновление:

Я просто искал этот предмет снова в хорошей книге Bill Wagner Эффективный C#, и он заявляет в "Объекте 10: Поймите Ловушки GetHashCode ()":

При определении типа, который никогда не будет использоваться в качестве ключа в контейнере, это не будет иметь значения. Типы, которые представляют средства управления окном, средства управления веб-страницей или соединения с базой данных, вряд ли будут использоваться в качестве ключей в наборе. В тех случаях ничего не сделайте. Все ссылочные типы будут иметь хэш-код, который корректен, даже если это очень неэффективно. [...] В большинстве типов, которые Вы создаете, лучший подход должен избежать существования GetHashCode () полностью.

... это - то, где я первоначально получил эту идею, что я не должен быть обеспокоен GetHashCode () всегда.

5
задан Cœur 6 August 2017 в 13:32
поделиться

5 ответов

Вы не должны подавлять это. Посмотрите, как реализован ваш метод equals. Я уверен, что он сравнивает один или несколько членов класса, чтобы определить равенство. Одного из этих членов часто бывает достаточно, чтобы отличить один объект от другого, и поэтому вы можете реализовать GetHashCode , вернув membername.GetHashCode (); .

6
ответ дан 18 December 2019 в 05:31
поделиться

Моя стоимость 0,10 доллара? Реализуйте GetHashCode.

Как бы вы ни говорили, что он вам никогда и никогда не понадобится, вы можете передумать, или у кого-то могут быть другие идеи о том, как использовать код. Создать рабочий GetHashCode несложно, и он гарантирует, что в будущем не будет никаких проблем.

5
ответ дан 18 December 2019 в 05:31
поделиться

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

5
ответ дан 18 December 2019 в 05:31
поделиться

Если вы reallio-trulio absosmurfly положительно , что вы никогда не будете использовать этот объект в качестве ключа к хеш-таблице, тогда ваше предложение разумно. Переопределить GetHashCode; сделать исключение.

Обратите внимание, что хеш-таблицы прячутся в маловероятных местах. Многие операторы последовательности LINQ используют внутренние реализации хэш-таблиц для ускорения работы. Отвергая реализацию GetHashCode, вы также отказываетесь от возможности использовать свой тип в различных запросах LINQ.Мне нравится создавать алгоритмы, использующие мемоизацию для увеличения скорости; мемоизаторы обычно используют хеш-таблицы. Следовательно, вы также отказываетесь от возможности запоминать вызовы методов, которые принимают ваш тип в качестве параметра.

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

Все, что сказал: давай. Вероятно, вы потратили больше времени на ввод вопроса, чем на его правильную реализацию. Просто сделай это.

14
ответ дан 18 December 2019 в 05:31
поделиться

Методы GetHashCode и Equals работают вместе, чтобы обеспечить семантику равенства на основе значений для вашего типа - вам следует реализовать их вместе.

Дополнительные сведения по этой теме см. В следующих статьях:

Бесстыдный плагин: Эти статьи написаны мной.

4
ответ дан 18 December 2019 в 05:31
поделиться
Другие вопросы по тегам:

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