Using lambda expression in place of IComparer argument

前端 未结 3 727
余生分开走
余生分开走 2020-12-08 08:57

Is it possible with C# to pass a lambda expression as an IComparer argument in a method call?

eg something like

var x = someIEnumerable.OrderBy(aClas         


        
相关标签:
3条回答
  • 2020-12-08 09:30

    If you're on .NET 4.5, you can use the static method Comparer<aClass>.Create.

    Documentation: Comparer<T>.Create Method .

    Example:

    var x = someIEnumerable.OrderBy(e => e.someProperty, 
        Comparer<aClass>.Create((x, y) => x.someProperty > y.SomeProperty ?  1 : x.someProperty < y.SomeProperty ?  -1 : 0)
        );
    
    0 讨论(0)
  • 2020-12-08 09:45

    As Jeppe points out, if you're on .NET 4.5, you can use the static method Comparer<T>.Create.

    If not, this is an implementation that should be equivalent:

    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);
        }
    }
    
    0 讨论(0)
  • 2020-12-08 09:46

    If you consistently want to compare projected keys (such as a single property), you can define a class that encapsulates all the key comparison logic for you, including null checks, key extraction on both objects, and key comparison using the specified or default inner comparer:

    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);
        }
    }
    

    For convenience, a factory method:

    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);
        }
    }
    

    You could then use this like so:

    var sortedSet = new SortedSet<MyClass>(KeyComparer.Create((MyClass o) => o.MyProperty));
    

    You can refer to my blog post for an expanded discussion of this implementation.

    0 讨论(0)
提交回复
热议问题