C#lambda表达式和IComparer

我使用lambda表达式在C#中排序和搜索数组。 我不想在我的类中实现IComparer接口,因为我需要对多个成员字段进行排序和搜索。

class Widget { public int foo; public void Bar() { Widget[] widgets; Array.Sort(widgets, (a, b) => a.foo.CompareTo(b.foo)); Widget x = new Widget(); x.foo = 5; int index = Array.BinarySearch(widgets, x, (a, b) => a.foo.CompareTo(b.foo)); } } 

虽然排序工作正常,但二进制搜索会产生编译错误无法将lambda表达式转换为类型’System.Collections.IComparer ‘,因为它不是委托类型 。 由于某种原因,Sort对IComparer和Comparison都有重载,但BinarySearch只支持IComparer。 经过一些研究,我发现了ComparisonComparer笨重的ComparisonComparer将比较转换为IComparer:

 public class ComparisonComparer : IComparer { private readonly Comparison comparison; public ComparisonComparer(Comparison comparison) { this.comparison = comparison; } int IComparer.Compare(T x, T y) { return comparison(x, y); } } 

这允许二进制搜索如下工作:

 int index = Array.BinarySearch( widgets, x, new ComparisonComparer((a, b) => a.foo.CompareTo(b.foo))); 

呸。 有更干净的方式吗?

好吧,一个选择是创建类似ProjectionComparer东西。 我在MiscUtil中有一个版本 – 它基本上是从投影中创建一个IComparer

所以你的例子是:

 int index = Array.BinarySearch(widgets, x, ProjectionComparer.Create(x => x.foo)); 

或者你可以在T[]上实现自己的扩展方法来做同样的事情:

 public static int BinarySearchBy( this TSource[] array, TSource value, Func keySelector) { return Array.BinarySearch(array, value, ProjectionComparer.Create(array, keySelector)); } 

您可以使用我的ValueComparer类 :

 int index = Array.BinarySearch( widgets, x, new ValueComparer(x => x.Foo) ); 

您可以通过传递多个lambda表达式来比较多个属性。

试试这个:

 public static class ComparisonEx { public static IComparer AsComparer(this Comparison @this) { if (@this == null) throw new System.ArgumentNullException("Comparison @this"); return new ComparisonComparer(@this); } public static IComparer AsComparer(this Func @this) { if (@this == null) throw new System.ArgumentNullException("Func @this"); return new ComparisonComparer((x, y) => @this(x, y)); } private class ComparisonComparer : IComparer { public ComparisonComparer(Comparison comparison) { if (comparison == null) throw new System.ArgumentNullException("comparison"); this.Comparison = comparison; } public int Compare(T x, T y) { return this.Comparison(x, y); } public Comparison Comparison { get; private set; } } } 

它允许您使用此代码:

 Comparison c = (x, y) => x == y ? 0 : (x <= y ? -1 : 1); IComparer icc = c.AsComparer(); Func f = (x, y) => x == y ? 0 : (x <= y ? -1 : 1); IComparer icf = f.AsComparer();