IEqualityComparer для анонимного типа
У меня есть это
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();
Я пробовал использовать общий LambdaComparer, но поскольку im использует анонимные типы, нет ассоциированного с ним типа.
"Помоги мне Оби Ван Кеноби, ты моя единственная надежда"
Ответы
Ответ 1
Хитрость заключается в создании компаратора, который работает только на предполагаемых типах. Например:
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);
Ответ 2
В большинстве случаев, когда вы сравниваете (для равенства или сортировки), вы заинтересованы в выборе ключей для сравнения, а не в методе равенства или сравнения (это идея API сортировки списка Python).
Здесь приведен пример сравнения коэффициентов равенства здесь.
Ответ 3
Я отмечаю, что ответ JaredPar не совсем отвечает на вопрос, поскольку установленные методы, такие как Distinct и Except, требуют IEqualityComparer<T>
not a 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
s: a Func<T, T, bool>
для проверки равенства и Func<T, T, int>
для выбора хеш-кода.