d--b
d--b

Reputation: 5779

How to create a Comparer from a lambda function easily?

I am wondering if there was a class provided in the .Net framework that implements IComparer and that can be constructed from a lambda function. That would be useful to be able to do:

void SortByLength(List<string> t)
{
    t = t.OrderBy(
           s => s, 
           Comparer<string>.FromLambda((s1,s2) => s1.Length.CompareTo(s2.Length))
        ).ToList();
}

It would be much easier than having to define a Comparer class each time. I know it is not complicated to create such a FromLambda method, but I was wondering if there was an existing way in the framework as I see this as being a pretty common feature.

Upvotes: 5

Views: 1994

Answers (4)

scottheckel
scottheckel

Reputation: 9244

I think you are over complicating things.

List<string> SortByLength(List<string> t) 
{ 
    return t.OrderBy( 
           s => s.Length
        ).ToList();     
} 

Upvotes: 1

Jeppe Stig Nielsen
Jeppe Stig Nielsen

Reputation: 61972

The other answers are from before the release of .NET 4.5. But with the BCL of .NET 4.5 (Visual Studio 2012), you simply say

Comparer<string>.Create((s1,s2) => s1.Length.CompareTo(s2.Length))

See the Comparer<T>.Create documentation.

Upvotes: 7

Mare Infinitus
Mare Infinitus

Reputation: 8182

Why would you make it that difficult?

Ordering the list by length is as simple as:

var ordered = list.OrderBy(s => s.Length);

If you really need that complicated stuff, the ComparisonComparer could help you out. Please have a look here: Converting Comparison to icomparer

This is building an IComparer from a lamda or delegate!

Here is the essential code from that example

public class ComparisonComparer<T> : IComparer<T>  
{  
    private readonly Comparison<T> _comparison;  

    public ComparisonComparer(Comparison<T> comparison)  
    {  
        _comparison = comparison;  
    }  

    public int Compare(T x, T y)  
    {  
        return _comparison(x, y);  
    }  
}  

Upvotes: 4

Rex M
Rex M

Reputation: 144142

I ended up creating additional overloads for the common methods (OrderBy, GroupBy, etc.) to take lambdas for IComparer and IEqualityComparer:

public static class EnumerableExtensions
{
    public static IEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, TKey, int> comparer)
    {
        return source.OrderBy(keySelector, new GenericComparer<TKey>(comparer));
    }

    private class GenericComparer<T> : IComparer<T>
    {
        private readonly Func<T, T, int> comparer;

        public GenericComparer(Func<T, T, int> comparer)
        {
            this.comparer = comparer;
        }

        public int Compare(T x, T y)
        {
            return this.comparer(x, y);
        }
    }
}

Upvotes: 3

Related Questions