Alex Rivera | Logout

Pass a lambda expression in place of IComparer or IEqualityComparer or any single-method interface?

Asked 2010-07-06T20:13:29.713
84

I happened to have seen some code where this guy passed a lambda expression to a ArrayList.Sort(IComparer here) or a IEnumerable.SequenceEqual(IEnumerable list, IEqualityComparer here) where an IComparer or an IEqualityComparer was expected.

I can't be sure if I saw it though, or I am just dreaming. And I can't seem to find an extension on any of these collections that accepts a Func<> or a delegate in their method signatures.

Is there such an overload/extension method? Or, if not, is it possible to muck around like this and pass an algorithm (read delegate) where a single-method interface is expected?

Update Thanks, everyone. That's what I thought. I must've been dreaming. I know how to write a conversion. I just wasn't sure if I'd seen something like that or just thought I'd seen it.

Yet another update Look, here, I found one such instance. I wasn't dreaming after all. Look at what this guy is doing here. What gives?

And here's another update: Ok, I get it. The guy's using the Comparison<T> overload. Nice. Nice, but totally prone to mislead you. Nice, though. Thanks.

Edit
Report

2 Answers

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

use it like this

ArrayList.Sort(new Comparer2<Product, string>(p => p.Name));
answered 2010-07-06T20:22:50.750
3

I vote for the dreaming theory.

You can't pass a function where an object is expected: derivatives of System.Delegate (which is what lambdas are) don't implement those interfaces.

What you probably saw is a use of the of the Converter<TInput, TOutput> delegate, which can be modeled by a lambda. Array.ConvertAll uses an instance of this delegate.

answered 2010-07-06T20:17:20.453

Your Answer