2009-10-25 35 views
8

我有以下类:LinQ在不同的使用自定义比较叶重复

public class SupplierCategory : IEquatable<SupplierCategory> 
{ 
    public string Name { get; set; } 
    public string Parent { get; set; } 

    #region IEquatable<SupplierCategory> Members 

    public bool Equals(SupplierCategory other) 
    { 
     return this.Name == other.Name && this.Parent == other.Parent; 
    } 

    #endregion 
} 

public class CategoryPathComparer : IEqualityComparer<List<SupplierCategory>> 
{ 
    #region IEqualityComparer<List<SupplierCategory>> Members 

    public bool Equals(List<SupplierCategory> x, List<SupplierCategory> y) 
    { 
     return x.SequenceEqual(y); 
    } 

    public int GetHashCode(List<SupplierCategory> obj) 
    { 
     return obj.GetHashCode(); 
    } 

    #endregion 
} 

而且我使用下面的LINQ查询:

CategoryPathComparer comparer = new CategoryPathComparer(); 
List<List<SupplierCategory>> categoryPaths = (from i in infoList 
                  select 
                  new List<SupplierCategory>() { 
                  new SupplierCategory() { Name = i[3] }, 
                  new SupplierCategory() { Name = i[4], Parent = i[3] }, 
                  new SupplierCategory() { Name = i[5], Parent = i[4] }}).Distinct(comparer).ToList(); 

但明显没有做什么,我想要它做,如下面的代码演示:

comp.Equals(categoryPaths[0], categoryPaths[1]); //returns True 

我是否以错误的方式使用它?为什么他们没有按照我的意图进行比较?

编辑: 为了证明该比较器不工作,下面的返回true,因为它应该:

List<SupplierCategory> list1 = new List<SupplierCategory>() { 
    new SupplierCategory() { Name = "Cat1" }, 
    new SupplierCategory() { Name = "Cat2", Parent = "Cat1" }, 
    new SupplierCategory() { Name = "Cat3", Parent = "Cat2" } 
}; 
List<SupplierCategory> list1 = new List<SupplierCategory>() { 
    new SupplierCategory() { Name = "Cat1" }, 
    new SupplierCategory() { Name = "Cat2", Parent = "Cat1" }, 
    new SupplierCategory() { Name = "Cat3", Parent = "Cat2" } 
}; 
CategoryPathComparer comp = new CategoryPathComparer(); 
Console.WriteLine(comp.Equals(list1, list2).ToString()); 
+0

Retag。没有C#3.5(请参阅http://stackoverflow.com/questions/247621/what-are-the-correct-version-numbers-for-c) – Vaccano 2009-11-02 23:10:28

回答

10

您的问题是你没有正确地实现IEqualityComparer

当你实现IEqualityComparer<T>,你必须实现这样GetHashCode任何两个相等的对象具有相同的哈希码。

否则,您会看到不正确的行为,正如您在此处看到的。

您应该执行的GetHashCode如下:(单位:this answer提供)

public int GetHashCode(List<SupplierCategory> obj) { 
    int hash = 17; 

    foreach(var value in obj) 
     hash = hash * 23 + obj.GetHashCode(); 

    return hash; 
} 

还需要在SupplierCategory覆盖GetHashCode要一致。例如:

public override int GetHashCode() { 
    int hash = 17; 
    hash = hash * 23 + Name.GetHashCode(); 
    hash = hash * 23 + Parent.GetHashCode(); 
    return hash; 
} 

最后,虽然你不需要,你应该重写EqualsSupplierCategory并使其调用Equals方法你IEquatable实现。

4

实际上,这个问题甚至包含在文档中: http://msdn.microsoft.com/en-us/library/bb338049.aspx

+0

您的意思是在社区内容? – SLaks 2009-11-03 04:17:23

+0

不,我的意思是该文档包含VB和C#上的代码示例,显示如何创建自己的比较器。它还显示了如何重写GetHashCode和Equals方法。 – 2009-11-03 18:08:07