Бывает, что коллекция содержит повторяющиеся объекты и требуется из неё получить коллекцию, содержащую только уникальные объекты. Этого можно добиться с помощью LINQ оператора Distinct, но есть одно но. Оператор Distinct() хорош с простыми типами, но если ваш объект представляет что-то посложнее (например экземпляр класса), то тут вас постигнет разочарование. Дубли так и останутся в коллекции. Это происходит потому, что оператор Distinct не умеет сравнивать экземпляры классов из-за их ссылочной природы.
Чтобы заставить оператор Distinct работать корректно потребуется создать класс, реализующий интерфейс IEqualityComparer<T>
и работающий с нашим классом (закрытый им). Этот интерфейс содержит всего два метода: bool Equals(T x, T y)
и int GetHashCode(T obj)
. Следовательно, реализовав эти два метода мы научим Distinct сравнивать объекты нашего класса, т.к. оператор Distinct имеет перегрузку, принимающую экземпляр, реализующий IEqualityComparer закрытый нашим классом.
Допустим наш класс определён следующим образом:
1 | public class Employee |
Тогда класс реализующий корректное сравнение экземпляров нашего класса будет выглядеть так:
1 | public class EmployeeComparer: IEqualityComparer<Employee> |
Теперь при вызове оператора Distinct на нашей коллекции ему требуется в параметрах передать экземпляр нашего сравнивателя EmployeeComparer:
1 | var uniqueEmployees = employees.Distinct(new EmployeeComparer()).ToList(); |
Такой запрос уже вернёт список уникальных экземпляров нашего класса.