Как использовать пользовательский сопоставитель с методом Linq Distinct?

Я читал книгу о Linq и видел, что метод Distinct имеет перегрузку, которая берет компаратор. Это было бы хорошим решением проблемы, с которой я хочу получить отдельные объекты из коллекции, но хочу, чтобы сравнение находилось в идентификаторе объекта, даже если другие свойства разные.

В соответствии с книгой, если у меня есть объект Gribulator, я должен был бы создать такой сопоставитель...

private class GribulatorComparer : IComparer<Gribulator> {
  public int Compare(Gribulator g1, Gribulator g2) {
    return g1.ID.CompareTo(g2.ID);
  }
}

... и затем используйте его так:

List<Gribulator> distinctGribulators
  = myGribulators.Distinct(new GribulatorComparer()).ToList();

Однако это дает следующие ошибки компилятора...

'System.Collections.Generic.List' не содержит определения для "Distinct" и лучшего метода перегрузки методом "System.Linq.Enumerable.Distinct(System.Collections.Generic.IEnumerable, System.Collections.Generic. IEqualityComparer) имеет некоторые недопустимые аргументы

Аргумент 2: невозможно преобразовать из "LinqPlayground.Program.GribulatorComparer" в "System.Collections.Generic.IEqualityComparer"

Я немного искал и видел множество примеров, которые используют такой код, но не жалуются на ошибки компилятора.

Что я делаю неправильно? Кроме того, это лучший способ сделать это? Я хочу одноразовое решение здесь, поэтому не хочу начинать изменять код для самой сущности. Я хочу, чтобы сущность оставалась как обычно, но только в этом месте, сравнивайте только по ID.

Спасибо за любую помощь.

Ответ 1

Вы реализуете свой компаратор как IComparer<T>, для перегрузки метода LINQ требуется реализация IEqualityComparer:

private class GribulatorComparer : IEqualityComparer<Gribulator> {
  public bool Equals(Gribulator g1, Gribulator g2) {
    return g1.ID == g2.ID;
  }
}

изменить:

Для пояснения интерфейс IComparer может использоваться для сортировки, поскольку это в основном то, что делает метод Compare().

Вот так:

items.OrderBy(x => new ItemComparer());

private class ItemComparer : IComparer<Item>
{
    public int Compare(Item x, Item y)
    {
        return x.Id.CompareTo(y.Id)
    }
}

Что будет сортировать вашу коллекцию с помощью этого компаратора, однако LINQ предоставляет способ сделать это для простых полей (например, int Id).

items.OrderBy(x => x.Id);