1
我需要在LINQ進行簡單的設置操作(例如工會,除了和Intersect)的IEqualityComparer <T>定製實現和設置操作
class Person {
public int Id { get; set; }
public string Name { get; set; }
public Person() { }
public Person(int id, string name) {
Id = id; Name = name;
}
}
的Comparer實現:
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"**
看來我的比較器沒有w掃。爲什麼?
@Ivan請記住,往往解決的GetHashCode /的Equals是相當複雜的,如果人是保存到數據庫的實體:在保存之前,ID爲0,同時節省後編號爲!= 0,所以哈希碼已經改變。所以如果你有一個HashSet或者一個字典那麼hashset/dictionary是ko,因爲它們在內部「緩存」了散列碼。 –
xanatos
2015-03-03 13:44:21
正如我理解你是正確的,我可以通過覆蓋方法:我的Person類中的ToString(),GetHashCode(),Equals()來避免執行IEqualityComparer。並且set-operations methos會默認超載正常工作(沒有IEqualityComparer parametr)? –
2015-03-03 14:19:44
@IvanStelmakh理論上,是的,但你應該注意* xanatos *的謹慎。如果'Id'可以在對象的生命週期中改變(並且可以,因爲setter是公共的),那麼對象在任何依賴哈希代碼的集合中都不會表現得很好。我建議不要修改類的默認行爲,除非你知道你在做什麼。 「IEqualityComparer」路由通常更好,因爲它在所有其他情況下保留了C#類的預期行爲。 – 2015-03-03 14:25:58