LinQ与自定义比较器不同,留下重复项 [英] LinQ distinct with custom comparer leaves duplicates
问题描述
我有以下课程:
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查询:
And i'm using the following linq query:
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();
但是不同的代码并不能满足我的要求,如以下代码所示:
But the distinct does not do what I want it to do, as the following code demonstrates:
comp.Equals(categoryPaths[0], categoryPaths[1]); //returns True
我是否以错误的方式使用它?为什么不将它们与我的预期相提并论?
Am I using this in a wrong way? why are they not compared as I intend them to?
为了演示比较器的工作原理,以下代码应返回true:
To demonstrate the the comparer does work, the following returns true as it should:
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());
推荐答案
您的问题是您没有正确实现IEqualityComparer
.
Your problem is that you didn't implement IEqualityComparer
correctly.
当您实现 IEqualityComparer<T>
时,您必须实施 GetHashCode
,以便任何两个相等对象具有相同的哈希码.
When you implement IEqualityComparer<T>
, you must implement GetHashCode
so that any two equal objects have the same hashcode.
否则,您将得到不正确的行为,如此处所见.
Otherwise, you will get incorrect behavior, as you're seeing here.
You should implement GetHashCode as follows: (courtesy of 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
以保持一致.例如:
You also need to override GetHashCode
in SupplierCategory
to be consistent. For example:
public override int GetHashCode() {
int hash = 17;
hash = hash * 23 + Name.GetHashCode();
hash = hash * 23 + Parent.GetHashCode();
return hash;
}
最后,尽管不需要,但您可能应该覆盖SupplierCategory
中的Equals
,并使其调用为IEquatable
实现的Equals
方法.
Finally, although you don't need to, you should probably override Equals
in SupplierCategory
and make it call the Equals
method you implemented for IEquatable
.
这篇关于LinQ与自定义比较器不同,留下重复项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!