我有以下课程:
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();
但是,distinct不能做我想做的事,如下面的代码所示:
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 :(得分:11)
您的问题是您未正确实施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;
}
您还需要覆盖GetHashCode
中的SupplierCategory
才能保持一致。例如:
public override int GetHashCode() {
int hash = 17;
hash = hash * 23 + Name.GetHashCode();
hash = hash * 23 + Parent.GetHashCode();
return hash;
}
最后,虽然您不需要,但您应该覆盖Equals
中的SupplierCategory
并让其调用您为Equals
实施的IEquatable
方法。
答案 1 :(得分:4)
实际上,这个问题甚至包含在文档中: http://msdn.microsoft.com/en-us/library/bb338049.aspx