[英]Overriding Object.Equals() instance method in C#; now Code Analysis/FxCop warning CA2218: “should also redefine GetHashCode”. Should I suppress this?
我在C#项目中有一个复杂的类,我希望能够进行相等测试。 这不是一个微不足道的阶级; 它包含各种标量属性以及对其他对象和集合的引用(例如IDictionary)。 为了它的价值,我的班级是密封的。
为了在我的系统中的其他地方启用性能优化(避免昂贵的网络往返的优化),我需要能够将这些对象的实例相互比较以实现相等 - 除了内置的引用相等 - 所以我重写了Object.Equals()实例方法。 但是,现在我已经这样做了,Visual Studio 2008的代码分析又称FxCop,我默认启用它,它引发了以下警告:
警告:CA2218:Microsoft.Usage:由于'MySuperDuperClass'重新定义了Equals,它还应该重新定义GetHashCode。
我想我理解这个警告的基本原理: 如果我要将这些对象用作集合中的键 ,那么哈希码很重要。 即看到这个问题 。 但是,我不打算将这些对象用作集合中的键。 永远。
感觉有理由压制警告,我在MSDN文档中查找了代码CA2218以获取警告的全名,因此我可以将SuppressMessage
属性应用于我的类,如下所示:
[SuppressMessage("Microsoft.Naming",
"CA2218:OverrideGetHashCodeOnOverridingEquals",
Justification="This class is not to be used as key in a hashtable.")]
但是,在进一步阅读时,我注意到以下内容:
如何修复违规行为
要修复违反此规则的行为,请提供GetHashCode的实现。 对于一对相同类型的对象,如果Equals的实现为该对返回true,则必须确保实现返回相同的值。
何时抑制警告
-----> 不要压制此规则的警告。 [箭头和重点我的]
所以,我想知道: 为什么我不应该按照我的计划来压制这个警告? 我的情况不是要求抑制吗? 我不想为这个永远不会被调用的对象编写GetHashCode()的实现,因为我的对象永远不会成为集合中的键。 如果我想要迂腐而不是抑制,那么用一个抛出NotImplementedException的实现覆盖GetHashCode()会更合理吗?
如果您定义的类型不会被用作容器中的键,那么这无关紧要。 表示窗口控件,网页控件或数据库连接的类型不太可能用作集合中的键。 在那些情况下,什么都不做。 即使效率非常低,所有引用类型都将具有正确的哈希码。 [...]在您创建的大多数类型中,最好的方法是完全避免GetHashCode()的存在。
...这就是我最初得到这个想法,我不必总是关注GetHashCode()。
如果你是reallio-trulio absosmurfly 肯定你永远不会使用这个东西作为哈希表的关键,那么你的提议是合理的。 覆盖GetHashCode; 让它抛出一个例外。
请注意,哈希表隐藏在不太可能的地方。 大量LINQ序列运算符在内部使用哈希表实现来加快速度。 通过拒绝GetHashCode的实现,您也拒绝在各种LINQ查询中使用您的类型。 我喜欢构建使用memoization来提高速度的算法; memoizers通常使用哈希表。 因此,您也拒绝记住将类型作为参数的方法调用的能力。
或者,如果你不想那么苛刻: 覆盖GetHashCode; 使它总是返回零。 这符合GetHashCode的语义要求; 两个相等的对象总是具有相同的哈希码。 如果它曾经被用作字典中的关键字,那么性能会很糟糕,但是当它出现时你可以处理它,你声称它永远不会。
所有这一切:来吧。 您可能花了更多时间来输入问题,而不是正确实现它。 去做就对了。
你不应该压制它。 看看你的equals方法是如何实现的。 我确信它比较了班上的一个或多个成员来确定平等。 其中一个成员通常足以区分一个对象,因此您可以通过返回membername.GetHashCode();
来实现GetHashCode
membername.GetHashCode();
。
我的价值0.10美元? 实现GetHashCode。
就像你说你永远不会需要它一样,你可能会改变主意,或者其他人可能对如何使用代码有其他想法。 工作GetHashCode并不难,并保证将来不会出现任何问题。
一旦你忘记了,或者另一个不知道的开发人员使用了这个,有人会有一个痛苦的错误来追查。 我建议只是正确实现GetHashCode,然后你就不用担心了。 或者只是不要将Equals用于特殊的相等比较案例。
GetHashCode
和Equals
方法协同工作,为您的类型提供基于值的相等语义 - 您应该一起实现它们。
有关此主题的更多信息,请参阅以下文章:
无耻的插件:这些文章是我写的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.