2015-04-06 67 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