2015-04-06 70 views
4

我有下面的類LINQ的不同不調用equals方法

public class ModInfo : IEquatable<ModInfo> 
{ 
    public int ID { get; set; } 
    public string MD5 { get; set; } 

    public bool Equals(ModInfo other) 
    { 
     return other.MD5.Equals(MD5); 
    } 

    public override int GetHashCode() 
    { 
     return MD5.GetHashCode(); 
    } 
} 

我使用像這樣的方法中的一些的數據加載到該類別的列表:

public void ReloadEverything() { 
    var beforeSort = new List<ModInfo>(); 
    // Bunch of loading from local sqlite database. 
    // not included since it's reload boring to look at 
    var modinfo = beforeSort.OrderBy(m => m.ID).AsEnumerable().Distinct().ToList(); 
} 

問題是Distinct()電話似乎並沒有做它的工作。仍然存在彼此相等的物體。

根據這篇文章:https://msdn.microsoft.com/en-us/library/vstudio/bb348436%28v=vs.100%29.aspx 這就是你應該如何做出不同的工作,但它似乎並沒有調用ModInfo對象上的Equals方法。 什麼可能導致這種情況發生?

值的示例:

modinfo[0]: id=2069, MD5 =0AAEBF5D2937BDF78CB65807C0DC047C 
modinfo[1]: id=2208, MD5 = 0AAEBF5D2937BDF78CB65807C0DC047C 

我不在乎哪個值被選擇,他們很可能是相同的,因爲無論如何的MD5值是一樣的。

+0

嘗試返回0而不是返回MD5.GetHashCode();在GetHashCode() – bit 2015-04-06 11:13:28

+1

這段代碼適用於我。你能否提供2個有問題的價值觀並指出你想要保留的價值? – 2015-04-06 11:18:03

+0

modinfo命令[0]:= ID 2069,MD5 = 0AAEBF5D2937BDF78CB65807C0DC047C modinfo命令[1]:= ID 2208,MD5 = 0AAEBF5D2937BDF78CB65807C0DC047C 我不關心的對象得到選定,如果MD5值是相同的,則的其餘部分對象也是 – 2015-04-06 11:22:14

回答

6

您還需要覆蓋Object.Equals,而不僅僅是執行IEquatable

如果您添加到您的類:

public override bool Equals(object other) 
{ 
    ModInfo mod = other as ModInfo; 
    if (mod != null) 
     return Equals(mod); 
    return false; 
} 

它應該工作。

請參見本文的詳細信息:Implementing IEquatable Properly

編輯:好,這裏是基於與GetHashCode的最佳做法稍有不同的實現。

public class ModInfo : IEquatable<ModInfo> 
{ 
    public int ID { get; set; } 
    public string MD5 { get; set; } 

    public bool Equals(ModInfo other) 
    { 
     if (other == null) return false; 
     return (this.MD5.Equals(other.MD5)); 
    } 

    public override int GetHashCode() 
    { 
     unchecked 
     { 
      int hash = 13; 
      hash = (hash * 7) + MD5.GetHashCode(); 
      return hash; 
     } 
    } 

    public override bool Equals(object obj) 
    { 
     ModInfo other = obj as ModInfo; 
     if (other != null) 
     { 
      return Equals(other); 
     } 
     else 
     { 
      return false; 
     } 
    } 
} 

你可以驗證:

ModInfo mod1 = new ModInfo {ID = 1, MD5 = "0AAEBF5D2937BDF78CB65807C0DC047C"}; 
ModInfo mod2 = new ModInfo {ID = 2, MD5 = "0AAEBF5D2937BDF78CB65807C0DC047C"}; 

// You should get true here 
bool areEqual = mod1.Equals(mod2); 

List<ModInfo> mods = new List<ModInfo> {mod1, mod2}; 

// You should get 1 result here 
mods = mods.Distinct().ToList(); 

What's with those specific numbers in GetHashCode?

+0

那隻會比較引用,而不是對象的實際值嗎? – 2015-04-06 11:33:34

+0

不,除非'ModInfo.Equals(ModInfo other)'的執行完成。 – 2015-04-06 11:42:56

+0

這個'Equals'方法正在調用你的equals方法,它進行實際的比較。您可能誤解了我:您需要**將此方法添加到您的班級,而不是將您的方法替換爲我的班級。 – 2015-04-06 11:54:21

0

添加

public bool Equals(object other) 
    { 
     return this.Equals(other as ModInfo) 
    } 

也看到這裏的建議如何實現平等成員:https://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx

+0

那隻會比較引用,而不是對象的實際值嗎?爲了補充一點,我不在乎ID(和我的對象上的一堆其他值),我只關心md5是否相等。 – 2015-04-06 11:33:41

+0

不,它會調用public bool Equals(ModInfo other)方法,因爲其他方法轉換爲ModInfo。當「other」爲null時,還需要修改以下處理方法:public bool Equals(ModInfo other) {if(other == null){return false;} return other.MD5.Equals(MD5); } – 2015-04-06 11:35:12