Передайте лямбда-выражение вместо IComparer или IEqualityComparer или какого-либо интерфейса отдельного метода?

Я, оказалось, видел некоторый код, куда этот парень передал лямбда-выражение ArrayList. Вид (IComparer здесь) или IEnumerable. SequenceEqual (список IEnumerable, IEqualityComparer здесь), где IComparer или IEqualityComparer ожидались.

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

Есть ли такой метод перегрузки/расширения? Или, в противном случае действительно ли возможно слоняться без дела как это и передать алгоритм (делегат чтения), где интерфейс отдельного метода ожидается?

Обновление Спасибо, все. Это - то, что я думал. Я, должно быть, мечтал. Я знаю, как записать преобразование. Я просто не был уверен, видел ли я что-то как этот или просто думал, что видел его.

Еще один Взгляд обновления, здесь, я нашел один такой экземпляр. Я не мечтал, в конце концов. Посмотрите на то, что этот парень делает здесь. Что дает?

И вот другое обновление: хорошо, я получаю его. Использование парня Comparison перегрузка.Мило. Хороший, но полностью склонный для введения в заблуждение Вас. Хороший, все же.Спасибо.

56
задан Water Cooler v2 6 July 2010 в 20:43
поделиться

5 ответов

Я голосую за теорию сновидений.

Вы не можете передать функцию там, где ожидается объект: производные от System.Delegate (которыми являются лямбды) не реализуют эти интерфейсы.

Вероятно, вы видели использование делегата Converter , который можно смоделировать с помощью лямбда-выражения. Array.ConvertAll использует экземпляр этого делегата.

3
ответ дан 26 November 2019 в 17:28
поделиться

Вы не можете передать его напрямую, однако вы можете сделать это, определив класс LambdaComparer, который исключает Func, а затем использует его в своем CompareTo.

Он не такой лаконичный, но вы можете сделать его короче с помощью некоторых творческих методов расширения на Func.

5
ответ дан 26 November 2019 в 17:28
поделиться
public class Comparer2<T, TKey> : IComparer<T>, IEqualityComparer<T>
{
    private readonly Expression<Func<T, TKey>> _KeyExpr;
    private readonly Func<T, TKey> _CompiledFunc
    // Constructor
    public Comparer2(Expression<Func<T, TKey>> getKey)
    {
        _KeyExpr = getKey;
        _CompiledFunc = _KeyExpr.Compile();
    } 

    public int Compare(T obj1, T obj2)
    {
        return Comparer<TKey>.Default.Compare(_CompiledFunc(obj1), _CompiledFunc(obj2));
    }

    public bool Equals(T obj1, T obj2)
    { 
        return EqualityComparer<TKey>.Default.Equals(_CompiledFunc(obj1), _CompiledFunc(obj2));
    }

    public int GetHashCode(T obj)
    {
         return EqualityComparer<TKey>.Default.GetHashCode(_CompiledFunc(obj));
    }
}

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

ArrayList.Sort(new Comparer2<Product, string>(p => p.Name));
6
ответ дан 26 November 2019 в 17:28
поделиться

Вы можете предоставить лямбда-выражение для метода Array.Sort, так как он требует метода, который принимает два объекта типа T и возвращает целое число. . Таким образом, вы можете предоставить лямбду следующего определения (a, b) => a.CompareTo (b) . Пример сортировки целочисленного массива по убыванию:

int[] array = { 1, 8, 19, 4 };

// descending sort 
Array.Sort(array, (a, b) => -1 * a.CompareTo(b));
11
ответ дан 26 November 2019 в 17:28
поделиться

У этих методов нет перегрузок, которые принимают делегат вместо интерфейса, но:

  • Обычно вы можете вернуть более простой ключ сортировки через делегат, который вы передаете в Enumerable.OrderBy
  • Аналогично, вы можете вызвать Enumerable.Select перед вызовом Enumerable. SequenceEqual
  • Не составит труда написать обертку, реализующую IEqualityComparer в терминах Func
  • F# позволяет реализовать такой интерфейс в терминах лямбды :)
3
ответ дан 26 November 2019 в 17:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: