Вопрос

у меня есть это

 var n = ItemList.Select(s => new { s.Vchr, s.Id, s.Ctr, s.Vendor, s.Description, s.Invoice }).ToList();
 n.AddRange(OtherList.Select(s => new { s.Vchr, s.Id, s.Ctr, s.Vendor, s.Description, s.Invoice }).ToList(););

Я хотел бы сделать это, если это разрешено

n = n.Distinct((x, y) => x.Vchr == y.Vchr)).ToList();

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

«Помоги мне, Оби Ван Кеноби, ты моя единственная надежда»

Это было полезно?

Решение

Хитрость заключается в том, чтобы создать компаратор, который работает только с выведенными типами.Например:

public class Comparer<T> : IComparer<T> {
  private Func<T,T,int> _func;
  public Comparer(Func<T,T,int> func) {
    _func = func;
  }
  public int Compare(T x,  T y ) {
    return _func(x,y);
  }
}

public static class Comparer {
  public static Comparer<T> Create<T>(Func<T,T,int> func){ 
    return new Comparer<T>(func);
  }
  public static Comparer<T> CreateComparerForElements<T>(this IEnumerable<T> enumerable, Func<T,T,int> func) {
    return new Comparer<T>(func);
  }
}

Теперь я могу сделать следующее...хакерское решение:

var comp = n.CreateComparerForElements((x, y) => x.Vchr == y.Vchr);

Другие советы

Большую часть времени, когда вы сравниваете (на равенство или сортировку), вас интересует выбор ключей для сравнения, а не сам метод равенства или сравнения (это идея API сортировки списка Python).

Есть пример сравнения ключей на равенство здесь.

Отмечу, что ответ JaredPar не совсем отвечает на вопрос, поскольку методы набора, такие как Distinct и Except, требуют IEqualityComparer<T> не IComparer<T>.Ниже предполагается, что IEquatable будет иметь подходящий GetHashCode и, безусловно, имеет подходящий метод Equals.

public class GeneralComparer<T, TEquatable> : IEqualityComparer<T>
{
    private readonly Func<T, IEquatable<TEquatable>> equatableSelector;

    public GeneralComparer(Func<T, IEquatable<TEquatable>> equatableSelector)
    {
        this.equatableSelector = equatableSelector;
    }

    public bool Equals(T x, T y)
    {
        return equatableSelector.Invoke(x).Equals(equatableSelector.Invoke(y));
    }

    public int GetHashCode(T x)
    {
        return equatableSelector(x).GetHashCode();
    }
}

public static class GeneralComparer
{
    public static GeneralComparer<T, TEquatable> Create<T, TEquatable>(Func<T, TEquatable> equatableSelector)
    {
        return new GeneralComparer<T, TEquatable>(equatableSelector);
    }
}

Где используется тот же вывод из трюка статического класса, что и в ответе JaredPar.

В более общем плане вы можете предоставить два Funcс:а Func<T, T, bool> проверить равенство и Func<T, T, int> чтобы выбрать хэш-код.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top