【发布时间】:2010-03-25 14:44:03
【问题描述】:
我的 C# 项目中有一个复杂的类,我希望能够对它进行相等性测试。它不是一个微不足道的类;它包含各种标量属性以及对其他对象和集合的引用(例如 IDictionary)。不管怎样,我的班级是封闭的。
为了在我的系统的其他地方启用性能优化(一种避免代价高昂的网络往返的优化),我需要能够将这些对象的实例相互比较以获得相等性——除了内置的引用相等性– 所以我重写了 Object.Equals() 实例方法。然而,既然我已经这样做了,Visual Studio 2008 的代码分析(又名 FxCop)(我默认保持启用)会发出以下警告:
警告:CA2218:Microsoft.Usage:自“MySuperDuperClass”以来 重新定义 Equals,它也应该重新定义 GetHashCode。
我想我理解这个警告的基本原理: 如果我要在集合中使用像 key 这样的对象,哈希码很重要。即see this question。 但是,我不会将这些对象用作集合中的键。永远。
觉得有理由取消警告,我查找了code CA2218 in the MSDN documentation 以获取警告的全名,因此我可以将SuppressMessage 属性应用于我的类,如下所示:
[SuppressMessage("Microsoft.Naming",
"CA2218:OverrideGetHashCodeOnOverridingEquals",
Justification="This class is not to be used as key in a hashtable.")]
但是,在进一步阅读时,我注意到以下内容:
如何解决违规问题
要修正违反此规则的行为, 提供一个实现 获取哈希码。对于一对对象 相同的类型,您必须确保 实现返回相同 如果您实施 Equals,则价值 为该对返回 true。
何时取消警告
-----> 不要抑制由此产生的警告 规则。 [箭头和强调我的]
所以,我想知道:为什么我不应该像我计划的那样隐藏这个警告?我的案子难道不应该被禁止吗?我不想为这个永远不会被调用的对象编写 GetHashCode() 的实现,因为我的对象永远不会成为集合中的键。如果我想变得迂腐而不是压抑,那么用引发 NotImplementedException 的实现覆盖 GetHashCode() 对我来说是否更合理?
更新: 我刚刚在 Bill Wagner 的好书 Effective C# 中再次查阅了这个主题,他在“第 10 项:理解 GetHashCode() 的陷阱”中指出:
如果您定义的类型不会 曾经被用作一个关键 容器,这无关紧要。类型 代表窗口控件、web 页面控件或数据库连接 不太可能被用作 收藏。在这些情况下,做 没有。所有引用类型都将 有一个正确的哈希码,甚至 如果它非常低效。 [...] 在 您创建的大多数类型,最好的 方法是避免存在 GetHashCode() 完全。
...这就是我最初得到这个想法的地方,我不需要总是关心 GetHashCode()。
【问题讨论】:
标签: c# warnings fxcop suppress-warnings