Использование выражения лямбда вместо аргумента IComparer
Возможно ли, чтобы С# передал лямбда-выражение в качестве аргумента IComparer в вызове метода?
например, что-то вроде
var x = someIEnumerable.OrderBy(aClass e => e.someProperty,
(aClass x, aClass y) =>
x.someProperty > y.SomeProperty ? 1 : x.someProperty < y.SomeProperty ? -1 : 0);
Я не могу заставить это скомпилировать, поэтому я не думаю, что это не так, но кажется очевидным синергизмом между лямбдами и анонимными делегатами, что я чувствую, что должен делать что-то глупое неправильно.
ТИА
Ответы
Ответ 1
Как указывает Джеппе, если вы используете .NET 4.5, вы можете использовать статический метод Comparer<T>.Create
.
Если нет, это реализация, которая должна быть эквивалентной:
public class FunctionalComparer<T> : IComparer<T>
{
private Func<T, T, int> comparer;
public FunctionalComparer(Func<T, T, int> comparer)
{
this.comparer = comparer;
}
public static IComparer<T> Create(Func<T, T, int> comparer)
{
return new FunctionalComparer<T>(comparer);
}
public int Compare(T x, T y)
{
return comparer(x, y);
}
}
Ответ 2
Если вы используете .NET 4.5, вы можете использовать статический метод Comparer<aClass>.Create
.
Документация: Comparer<T>.Create
Способ.
Пример:
var x = someIEnumerable.OrderBy(e => e.someProperty,
Comparer<aClass>.Create((x, y) => x.someProperty > y.SomeProperty ? 1 : x.someProperty < y.SomeProperty ? -1 : 0)
);
Ответ 3
Если вы последовательно хотите сравнить проецируемые ключи (например, одно свойство), вы можете определить класс, который инкапсулирует всю логику сравнения ключей для вас, включая нулевые проверки, извлечение ключей для обоих объектов и сравнение ключей с использованием указанного или внутренний компаратор по умолчанию:
public class KeyComparer<TSource, TKey> : Comparer<TSource>
{
private readonly Func<TSource, TKey> _keySelector;
private readonly IComparer<TKey> _innerComparer;
public KeyComparer(
Func<TSource, TKey> keySelector,
IComparer<TKey> innerComparer = null)
{
_keySelector = keySelector;
_innerComparer = innerComparer ?? Comparer<TKey>.Default;
}
public override int Compare(TSource x, TSource y)
{
if (object.ReferenceEquals(x, y))
return 0;
if (x == null)
return -1;
if (y == null)
return 1;
TKey xKey = _keySelector(x);
TKey yKey = _keySelector(y);
return _innerComparer.Compare(xKey, yKey);
}
}
Для удобства метод factory:
public static class KeyComparer
{
public static KeyComparer<TSource, TKey> Create<TSource, TKey>(
Func<TSource, TKey> keySelector,
IComparer<TKey> innerComparer = null)
{
return new KeyComparer<TSource, TKey>(keySelector, innerComparer);
}
}
Затем вы можете использовать его так:
var sortedSet = new SortedSet<MyClass>(KeyComparer.Create((MyClass o) => o.MyProperty));
Вы можете обратиться к моему сообщению в блоге для расширенного обсуждения этой реализации.