簡體   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