หากคุณไม่ต้องการเพิ่มไลบรารี่ MoreLinq ลงในโครงการของคุณเพื่อรับDistinctBy
ฟังก์ชั่นการใช้งานคุณสามารถรับผลลัพธ์สุดท้ายที่เหมือนกันโดยใช้Distinct
เมธอดoverload ของ Linq ซึ่งIEqualityComparer
ขัดแย้งกัน
คุณเริ่มต้นด้วยการสร้างคลาสเครื่องมือเปรียบเทียบความเท่าเทียมกันทั่วไปที่กำหนดเองที่ใช้ไวยากรณ์แลมบ์ดาเพื่อทำการเปรียบเทียบแบบกำหนดเองของคลาสทั่วไปสองอินสแตนซ์:
public class CustomEqualityComparer<T> : IEqualityComparer<T>
{
Func<T, T, bool> _comparison;
Func<T, int> _hashCodeFactory;
public CustomEqualityComparer(Func<T, T, bool> comparison, Func<T, int> hashCodeFactory)
{
_comparison = comparison;
_hashCodeFactory = hashCodeFactory;
}
public bool Equals(T x, T y)
{
return _comparison(x, y);
}
public int GetHashCode(T obj)
{
return _hashCodeFactory(obj);
}
}
จากนั้นในรหัสหลักของคุณคุณใช้มันเพื่อ:
Func<Person, Person, bool> areEqual = (p1, p2) => int.Equals(p1.Id, p2.Id);
Func<Person, int> getHashCode = (p) => p.Id.GetHashCode();
var query = people.Distinct(new CustomEqualityComparer<Person>(areEqual, getHashCode));
Voila! :)
ข้างต้นจะถือว่าสิ่งต่อไปนี้:
- คุณสมบัติ
Person.Id
เป็นประเภทint
people
คอลเลกชันไม่ได้มีองค์ประกอบ null ใด ๆ
หากการเก็บรวบรวมอาจมีค่า Null ให้ทำการเขียน lambdas ใหม่เพื่อตรวจสอบค่า Null เช่น:
Func<Person, Person, bool> areEqual = (p1, p2) =>
{
return (p1 != null && p2 != null) ? int.Equals(p1.Id, p2.Id) : false;
};
แก้ไข
วิธีนี้คล้ายกับคำตอบใน Vladimir Nesterovsky แต่ง่ายกว่า
นอกจากนี้ยังคล้ายกับคำตอบของ Joel แต่อนุญาตให้ใช้ตรรกะเปรียบเทียบที่ซับซ้อนที่เกี่ยวข้องกับคุณสมบัติหลายอย่าง
อย่างไรก็ตามหากวัตถุของคุณสามารถแตกต่างกันไปตามId
นั้นผู้ใช้รายอื่นให้คำตอบที่ถูกต้องว่าสิ่งที่คุณต้องทำคือแทนที่การใช้งานเริ่มต้นของGetHashCode()
และEquals()
ในPerson
ชั้นเรียนของคุณแล้วใช้วิธีการนอกกรอบDistinct()
ของ Linq เพื่อกรอง ทำซ้ำใด ๆ