c# - 在 C# 中覆盖 Object.Equals() 实例方法;现在代码分析/FxCop 警告 CA2218 : "should also redefine GetHashCode". 我应该抑制这个吗?

标签 c# warnings fxcop suppress-warnings

我的 C# 项目中有一个复杂的类,我希望能够对其进行相等性测试。这不是一个简单的类;它包含各种标量属性以及对其他对象和集合(例如 IDictionary)的引用。不管怎样,我的类(class)是密封的。

为了在我的系统中的其他地方启用性能优化(一种避免昂贵的网络往返的优化),我需要能够将这些对象的实例相互比较是否相等——除了内置的引用相等– 所以我重写了 Object.Equals() 实例方法。但是,既然我已经这样做了,Visual Studio 2008 的代码分析 a.k.a. FxCop(我在默认情况下保持启用)会引发以下警告:

warning : CA2218 : Microsoft.Usage : Since 'MySuperDuperClass' redefines Equals, it should also redefine GetHashCode.

我想我理解这个警告的基本原理:如果我要在集合中使用像这样的对象,哈希码很重要。即 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.")]

然而,在进一步阅读时,我注意到以下几点:

How to Fix Violations

To fix a violation of this rule, provide an implementation of GetHashCode. For a pair of objects of the same type, you must ensure that the implementation returns the same value if your implementation of Equals returns true for the pair.

When to Suppress Warnings

-----> Do not suppress a warning from this rule. [arrow & emphasis mine]

所以,我想知道:为什么我不应该像我计划的那样隐藏这个警告?我的案例不值得隐藏吗?我不想为这个永远不会被调用的对象编写 GetHashCode() 的实现,因为我的对象永远不会成为集合中的键。如果我想学究气而不是压抑,用抛出 NotImplementedException 的实现重写 GetHashCode() 是否更合理?


更新:我刚刚在 Bill Wagner 的好书 Effective C# 中再次查阅了这个主题,他在“第 10 项:了解 GetHashCode() 的陷阱”中指出:

If you're defining a type that won't ever be used as the key in a container, this won't matter. Types that represent window controls, web page controls, or database connections are unlikely to be used as keys in a collection. In those cases, do nothing. All reference types will have a hash code that is correct, even if it is very inefficient. [...] In most types that you create, the best approach is to avoid the existence of GetHashCode() entirely.

...这就是我最初的想法,我不必总是担心 GetHashCode()。

最佳答案

如果您是 reallio-trulio absosmurfly 肯定您永远不会将该事物用作哈希表的键,那么您的建议是合理的。 覆盖 GetHashCode;让它抛出异常。

请注意,哈希表隐藏在不太可能的地方。许多 LINQ 序列运算符在内部使用哈希表实现来加快速度。通过拒绝 GetHashCode 的实现,您也拒绝在各种 LINQ 查询中使用您的类型。我喜欢构建使用内存来提高速度的算法;内存器通常使用哈希表。因此,您也拒绝内存将您的类型作为参数的方法调用的能力。

或者,如果您不想那么苛刻:Override GetHashCode;使其始终返回零。 满足 GetHashCode 的语义要求;两个相等的对象总是具有相同的哈希码。如果它曾经用作字典中的键,性能将会很糟糕,但您可以在它出现时处理该问题,您声称它永远不会出现。

总而言之:来吧。您输入问题所花费的时间可能比正确实现问题所花费的时间还多。就去做吧。

关于c# - 在 C# 中覆盖 Object.Equals() 实例方法;现在代码分析/FxCop 警告 CA2218 : "should also redefine GetHashCode". 我应该抑制这个吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2516428/

相关文章:

c# - 有人可以解释 Microsoft Unity 吗?

c# - Xamarin 形成值转换器导致无限循环

perl - 在Perl中,当我使用@_ [0],@ _ [1]等访问子例程的参数时,为什么会收到警告?

objective-c - 警告 : passing argument 1 of 'CGPathMoveToPoint' discards qualifiers from pointer target type

.net - 有没有办法识别未使用或过时的 FxCop 消息抑制?

javascript - 将 C# 数据结果传递给 JavaScript 变量

c# - 缓存项永不过期

r - tryCatch() 显然忽略了警告

c# - FxCop:用于检查程序集信息值的自定义规则

c# - 在 C# 中抛出保留异常时会出现什么问题?