88

C# 是否可以在方法调用中将 lambda 表达式作为 IComparer 参数传递?

例如类似的东西

var x = someIEnumerable.OrderBy(aClass e => e.someProperty, 
(aClass x, aClass y) => 
  x.someProperty > y.SomeProperty ?  1 : x.someProperty < y.SomeProperty ?  -1 : 0);

我无法完全编译它,所以我猜不是,但 lambda 和匿名代表之间似乎有如此明显的协同作用,我觉得我一定是在做一些愚蠢的错误。

TIA

4

3 回答 3

106

如果您使用的是 .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)
    );
于 2013-05-30T15:00:54.960 回答
68

正如 Jeppe 指出的那样,如果您使用的是 .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);
    }
}
于 2013-05-30T15:04:47.467 回答
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);
    }
}

为方便起见,工厂方法:

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

你可以参考我的博客文章来详细讨论这个实现。

于 2016-03-19T20:15:21.140 回答