簡體   English   中英

警告:“...覆蓋Object.Equals(對象o)但不覆蓋Object.GetHashCode()”

[英]Warning: “… overrides Object.Equals(object o) but does not override Object.GetHashCode()”

我重寫了我班級的Equals()來比較Guid類型的ID值。

然后Visual Studio警告:

...重寫Object.Equals(object o)但不覆蓋Object.GetHashCode()

所以我然后也像這樣覆蓋它的GetHashCode():

public partial class SomeClass
{
    public override bool Equals(Object obj)
    {
        //Check for null and compare run-time types.
        if (obj == null || this.GetType() != obj.GetType()) return false;

        return this.Id == ((SomeClass)obj).Id;
    }

    public override int GetHashCode()
    {
        return this.Id.GetHashCode();
    }
}

它似乎工作。 我做得對嗎? 記住Id是Guid類型。 我的類是實體框架對象是否重要?

正如其他人所說的那樣,在平等中使用反思似乎很狡猾。 拋開這一點,讓我們專注於GetHashCode。

您必須不違反GetHashCode的主要規則是, 如果兩個對象相等,則它們必須具有相同的哈希碼 或者,相同的說法是, 如果兩個對象具有不同的哈希碼,那么它們必須是不相等的。 你的實現看起來不錯。

你可以自由地違反反過來。 也就是說,如果兩個對象具有相同的哈希碼,則允許它們相等或不相等,如您所見。

我假設“Id”是一個不可變的屬性。 如果“Id”可以在對象的生命周期內更改,那么將對象放入哈希表時可能會出現問題。 考慮確保在計算相等性和哈希碼時僅使用不可變屬性。

您的實現看起來不錯,但您提出問題的事實表明您可能無法掌握構建GetHashCode實現的所有細微因素。 一個好的開始是我關於這個主題的文章:

http://ericlippert.com/2011/02/28/guidelines-and-rules-for-gethashcode/

它對我來說是正確的。 每當我做這樣的事情時,我通常也會實現IEquatable以便在相同編譯時類型的變量之間進行比較會更有效。

public partial class SomeClass : IEquatable<SomeClass>
{
     public override bool Equals(Object obj)
     {
         return Equals(obj as SomeClass);
     }
     public bool Equals(SomeClass obj)
     {
         if (obj == null) 
             return false;
         return Id == obj.Id;
     }
     public override int GetHashCode()
     {
         return Id.GetHashCode();
     }
} 

此結構還允許具有相同Id的更多派生對象進行比較,使其等於較少派生的對象。 如果這不是所需的行為,那么您還必須像在問題中那樣比較類型。

if (obj.GetType() != typeof(SomeClass)) return false;

既然你沒有處理一個密封的類,我建議不要像這樣檢查類的相等性this.GetType() != obj.GetType() SomeClass任何子類也應該能夠參與Equals ,所以你可能想要使用它:

if (obj as SomeClass == null) return false;

傳統上, Equals以這樣的方式實現:如果兩個對象在各方面都完全相同,那么它們將只是“等於”。 例如,如果您有兩個對象代表數據庫中的同一個對象,但是其中一個對象具有與另一個不同的Name屬性,則對象不會被視為“Equal”,並且如果可能,應避免生成相同的“Hashcode” 。

最好是在“不平等”方面犯錯,而不是冒險調用兩個不相等的對象。 這就是對象的默認實現使用對象本身的內存位置的原因:除非它們是完全相同的對象,否則不會將兩個對象視為“相等”。 所以我要說除非你想以這樣的方式編寫GetHashCodeEquals來檢查它們所有屬性的相等性,否則最好不要覆蓋任何一種方法。

如果您有一個數據結構(如HashSet ),您特別希望根據ID值確定相等性,則可以為該數據結構提供特定的IEqualityComparer實現。

你得到了第一個問題的優秀答案:

我做得對嗎?

我會回答你的第二個問題

我的類是實體框架對象是否重要?

是的,這很重要。 實體框架在內部使用了很多HashSet 例如,動態代理使用HashSet表示集合導航屬性,而EntityObject使用EntityCollection ,而EntityCollection又在內部使用HashSet

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM