Nếu bạn không muốn thêm thư viện MoreLinq vào dự án của mình chỉ để có được DistinctBy
chức năng thì bạn có thể nhận được kết quả cuối cùng tương tự bằng cách sử dụng quá tải Distinct
phương thức của Linq trong một IEqualityComparer
đối số.
Bạn bắt đầu bằng cách tạo một lớp so sánh đẳng thức tùy chỉnh chung sử dụng cú pháp lambda để thực hiện so sánh tùy chỉnh hai trường hợp của một lớp chung:
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);
}
}
Sau đó, trong mã chính của bạn, bạn sử dụng nó như vậy:
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! :)
Trên đây giả định như sau:
- Tài sản
Person.Id
thuộc loạiint
- Bộ
people
sưu tập không chứa bất kỳ phần tử null nào
Nếu bộ sưu tập có thể chứa null thì chỉ cần viết lại lambdas để kiểm tra null, ví dụ:
Func<Person, Person, bool> areEqual = (p1, p2) =>
{
return (p1 != null && p2 != null) ? int.Equals(p1.Id, p2.Id) : false;
};
BIÊN TẬP
Cách tiếp cận này tương tự như trong câu trả lời của Vladimir Nesterovsky nhưng đơn giản hơn.
Nó cũng tương tự như câu trả lời của Joel nhưng cho phép logic so sánh phức tạp liên quan đến nhiều thuộc tính.
Tuy nhiên, nếu các đối tượng của bạn chỉ có thể khác nhau trước Id
đó thì một người dùng khác đã đưa ra câu trả lời chính xác rằng tất cả những gì bạn cần làm là ghi đè các cài đặt mặc định GetHashCode()
và Equals()
trong Person
lớp của bạn , sau đó chỉ cần sử dụng Distinct()
phương thức ngoài luồng của Linq để lọc ra bất kỳ bản sao.