Если вы не хотите добавлять библиотеку MoreLinq в свой проект просто для того, чтобы получить DistinctBy
функциональность, вы можете получить тот же конечный результат, используя перегрузку метода Linq, Distinct
которая принимает 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));
Вуаля! :)
Вышесказанное предполагает следующее:
- Свойство
Person.Id
типаint
people
Коллекция не содержит каких - либо элементов неопределенные
Если коллекция может содержать нули, просто перепишите лямбда-выражения для проверки на ноль, например:
Func<Person, Person, bool> areEqual = (p1, p2) =>
{
return (p1 != null && p2 != null) ? int.Equals(p1.Id, p2.Id) : false;
};
РЕДАКТИРОВАТЬ
Этот подход похож на ответ в ответе Владимира Нестеровского, но проще.
Это также похоже на ответ в ответе Джоэла, но допускает сложную логику сравнения, включающую несколько свойств.
Однако, если ваши объекты могут только когда-либо отличаться, Id
другой пользователь дал правильный ответ, что все, что вам нужно сделать, это переопределить реализации по умолчанию GetHashCode()
и Equals()
в вашем Person
классе, а затем просто использовать Distinct()
готовый метод Linq для фильтрации любые дубликаты.