我需要在linq中执行简单的set-operations(例如Union,Except和Intersect)
class Person {
public int Id { get; set; }
public string Name { get; set; }
public Person() { }
public Person(int id, string name) {
Id = id; Name = name;
}
}
比较实施:
class PersonComparer : IEqualityComparer<Person> {
public bool Equals(Person x, Person y) {
return x.Id == y.Id;
}
public int GetHashCode(Person p) {
return p.GetHashCode();
}
}
填充列表:
var list1 = new List<Person>();
list1.Add(new Person(1, "John"));
list1.Add(new Person(2, "Peter"));
list1.Add(new Person(3, "Mike"));
var list2 = new List<Person>();
list2.Add(new Person(2, "Peter"));
list2.Add(new Person(3, "Mike"));
list2.Add(new Person(4, "Fred"));
var comparer = new PersonComparer();
var list3 = list1.Intersect(list2, comparer).ToList(); // **Empty List**
var list4 = list1.Except(list2, comparer).ToList(); // **"John", "Peter", "Mike"**
似乎我的比较器不起作用。为什么呢?
答案 0 :(得分:4)
问题是您GetHashCode(Person p)
的实施。如MSDN中所述:
需要实现以确保
Equals
方法 为两个对象x
和y
返回 true ,然后返回由GetHashCode
的{{1}}方法必须等于x
返回的值。
在您的情况下,y
可能会为内存中的每个p.GetHashCode()
返回不同的值,即使它们具有相同的p
- 即Id
的两个不同实例可能具有相同的Person
但不同的哈希码 - 因此这不足以满足上面提到的Id
的正确实现的要求。相反,使用这样的东西:
GetHashCode(Person p)