IEqualityComparer <t>自定义实现和设置操作</t>

时间:2015-03-03 13:30:09

标签: c# linq iequalitycomparer set-operations

我需要在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"**

似乎我的比较器不起作用。为什么呢?

1 个答案:

答案 0 :(得分:4)

问题是您GetHashCode(Person p)的实施。如MSDN中所述:

  

需要实现以确保Equals方法   为两个对象xy返回 true ,然后返回由   GetHashCode的{​​{1}}方法必须等于x返回的值。

在您的情况下,y可能会为内存中的每个p.GetHashCode()返回不同的值,即使它们具有相同的p - 即Id的两个不同实例可能具有相同的Person但不同的哈希码 - 因此这不足以满足上面提到的Id的正确实现的要求。相反,使用这样的东西:

GetHashCode(Person p)