繁体   English   中英

为什么没有 Equals() 的 GetHashCode() 没有警告

[英]Why no warning for GetHashCode() without Equals()

我为标题的简短道歉,但实际的标题会有点太长。 这是实际的长标题:

为什么在没有GetHashCode() ) 的情况下覆盖Equals()时出现警告,但在没有Equals() ) 的情况下覆盖GetHashCode()时没有警告?

我也提前道歉,这不是一个“Y 中的 X 是什么”类型的问题,它更像是一个“我观察到 X;我错过了什么吗?” 类型的问题。

因此,请考虑以下事项:

class A
{
    public override bool Equals( object other ) => true; //warning CS0659
}

class B
{
    public override int GetHashCode() => 42; //No warning
}

我知道警告 CS0659“类覆盖 Object.Equals(object o) 但不覆盖 Object.GetHashCode()”背后的原因。 I do not agree with those reasons, because Equals() is perfectly viable for a mutable class, whereas such a class must of course never be used as a key in a hash map, and therefore must not have a GetHashCode() , but my反对是无关紧要的,在任何情况下,收到您不需要的警告都不是问题,因为您可以随时禁用它。

但是,当您可以想到可以使用的警告但您没有收到这样的警告时,就会出现问题。

这就是上面的class B演示的内容。 重写GetHashCode()而不重写Equals()几乎可以肯定是一个严重的错误,但没有警告。 不是 C# 编译器,也不是 ReSharper。

有谁知道为什么?

有什么我想念的吗?

是否存在警告,但我必须知道一些配置魔法才能将其从编译器中剔除?

难道我必须以某种奇怪的方式声明我的 class ,比如public sealedalbino或其他什么?

没有警告是否有任何正当理由?

编辑

到目前为止,这个问题已经有了一些答案,它们几乎都是 state 相同的事情:没有警告,因为没有违反GetHashCode()Equals()的合同。

女士们先生们,你们没有抓住重点。

(或者我应该说我为未能更清楚地说明这一点而道歉。)

支持没有此警告的“不违反合同”论点与试图支持没有其他警告(例如“从不使用事件”)一样有意义,理由是通过声明一个事件并且从不使用它也不会违反任何合同。

好吧,首先,如果我通过声明一个事件并且从不使用它而违反了某些合同,我会期待一个错误,而不是一个警告。

但最重要的是,声明一个事件并且从不使用它是一个严重而阴险的错误,因此无论合同如何,都需要警告。

事实上,有一个警告!

它是 CS0067“从未使用过事件 '{0}'”。

看? 警告不需要违反任何合同。

所以这个论点被吹得水泄不通了。

请问还有其他的arguments吗?

GetHashCode()方法应该反映Equals逻辑; 规则是:

  • 如果两件事相等( Equals(...) == true ),那么它们必须为GetHashCode()返回相同的值
  • 如果GetHashCode()相等,则它们不必相同; 这是一个冲突,将调用Equals来查看它是否是真正的相等。

当您覆盖GetHashCode()方法时,不会被破坏或违反(根据Equals() / GetHashCode()合约)。 如果它是相同的 object,则Equals()方法仍然返回true ,并且对于所有其他 object 将返回false 当您覆盖GetHashCode()方法时,没有办法违反合同。

  • Two references to the exact same object will return the same GetHashCode() since it is in fact the same object and the state of the object hasn't changed in the meantime, as required by the contract of GetHashCode() . (是Equals() => 相同的GetHashCode()

  • 此外,当两个 hash 代码不同时,这意味着这两个对象不能相互Equals() 但是由于两个不同的对象无论如何都不是Equals() (当没有被覆盖时),这个要求是自动满足的。 (不同的GetHashCode() => 不是Equals()

由于您没有违反任何合同,因此编译器不会收到任何警告(与您提到的警告 CS0659不同)。 在这种情况下,您不需要重写Equals()方法。

请参阅Microsoft Object.GetHashCode() 文档
要点是:
相等的对象返回相等的 hash 代码。 但是,反之则不然:相等的 hash 代码并不意味着 object 相等,因为不同(不相等)的对象可以具有相同的 hash 代码
与 Equality HashCode 不同的是,它不是持久的和特定于平台的。 这能解释吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM