Jeśli nie chcesz dodawać biblioteki MoreLinq do swojego projektu tylko po to, aby uzyskać DistinctBy
funkcjonalność, możesz uzyskać ten sam wynik końcowy, używając przeciążenia metody Linq, Distinct
która przyjmuje IEqualityComparer
argument.
Zaczynasz od utworzenia ogólnej niestandardowej klasy porównującej równość, która używa składni lambda do wykonania niestandardowego porównania dwóch wystąpień klasy ogólnej:
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);
}
}
Następnie w głównym kodzie używasz go w następujący sposób:
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! :)
Powyższe zakłada, co następuje:
- Właściwość
Person.Id
jest typuint
people
Zbiór nie zawiera żadnych elementów zerowych
Jeśli kolekcja może zawierać wartości null, po prostu przepisz lambdy, aby sprawdzić, czy null, np .:
Func<Person, Person, bool> areEqual = (p1, p2) =>
{
return (p1 != null && p2 != null) ? int.Equals(p1.Id, p2.Id) : false;
};
EDYTOWAĆ
To podejście jest podobne do tego w odpowiedzi Władimira Niestierowskiego, ale jest prostsze.
Jest również podobny do tego w odpowiedzi Joela, ale pozwala na złożoną logikę porównań obejmującą wiele właściwości.
Jeśli jednak Twoje obiekty mogą się różnić tylko do tego Id
czasu, inny użytkownik udzielił poprawnej odpowiedzi, że wszystko, co musisz zrobić, to zastąpić domyślne implementacje GetHashCode()
i Equals()
w swojej Person
klasie, a następnie użyć Distinct()
gotowej metody Linq do filtrowania wszystkie duplikaty.