IEqualityComparer<T> 自定义实现和设置操作
IEqualityComparer<T> custom implementation and set-operations
我需要在 linq 中执行简单的集合操作(例如 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"**
看来我的比较器不起作用。为什么?
问题是您对 GetHashCode(Person p)
的实施。如 MSDN 中所述:
Implementations are required to ensure that if the Equals
method
returns true for two objects x
and y
, then the value returned by the
GetHashCode
method for x
must equal the value returned for y
.
在您的情况下,p.GetHashCode()
可能 return 内存中每个 p
的不同值,即使它们具有相同的 Id
— 即两个不同的值Person
的实例可能具有相同的 Id
但哈希码不同——因此这不足以满足上述正确实现 GetHashCode(Person p)
的要求。相反,使用这样的东西:
public int GetHashCode(Person p) {
return p.Id;
}
我需要在 linq 中执行简单的集合操作(例如 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"**
看来我的比较器不起作用。为什么?
问题是您对 GetHashCode(Person p)
的实施。如 MSDN 中所述:
Implementations are required to ensure that if the
Equals
method returns true for two objectsx
andy
, then the value returned by theGetHashCode
method forx
must equal the value returned fory
.
在您的情况下,p.GetHashCode()
可能 return 内存中每个 p
的不同值,即使它们具有相同的 Id
— 即两个不同的值Person
的实例可能具有相同的 Id
但哈希码不同——因此这不足以满足上述正确实现 GetHashCode(Person p)
的要求。相反,使用这样的东西:
public int GetHashCode(Person p) {
return p.Id;
}