上次我们分析了Array.Sort<T>方法的实现方式,并了解到类库会为一些特例而使用高性能的排 序方式——int数组便是这样一例,因此从测试结果上来看其性能特别高。不过从数据上看,即便是在普 通的情况下,Array.Sort<T>的性能也比LINQ排序要高。不过也有朋友从测试中得出的结论正好相 反,这又是为什么呢?那么现在,我们再来分析一下LINQ排序的实现方式吧,希望这样可以了解到两者性 能差别的秘密。
只可惜,LINQ排序的代码在System.Core.dll程序集中,微软没有发布这部分源代码,我们只得使 用.NET Reflector来一探究竟了。
LINQ排序接口的定义、使用及扩展
所谓LINQ排序,便是使用定义在System.Linq.Enumerable类中的几个扩展方法,它们是:
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector);
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer);
public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector);
public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer);
为了使用时的方便,我往往会补充一些额外的接口,例如:
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, bool decending)
{
return decending ?
source.OrderByDescending(keySelector) :
source.OrderBy(keySelector);
}
这样在使用时,便可以使用一个布尔值来表示排序的方向(升序或是降序)而不需要从两个方法之间 “手动”选择一个。此外,构造一个 IComparer<TKey>类型也实在有些麻烦,于是我按照 Array.Sort<T>的做法重新继续扩展了一个使用委托对象作为“比较器”的接口:
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Comparison<TKey> compare, bool decending)
{
return decending ?
source.OrderByDescending(keySelector, new FunctorComparer<TKey>(compare)) :
source.OrderBy(keySelector, new FunctorComparer<TKey>(compare));
}