为什么有OrderBy和OrderByDescending而不是OrderBy(SortOrder)?

时间:2010-07-14 21:32:40

标签: c# .net linq api

目前,如果我们将订购方向作为外部依赖关系,我们必须使用 if 来应用此方向:

public static IEnumerable<FileInfo> getlist(string directory, string searchPattern, string order)
{
    var files = new DirectoryInfo(directory).EnumerateFiles(searchPattern);

    if (order == "A")
        return files.OrderBy(f => f.CreationTime);

    return files.OrderByDescending(f => f.CreationTime);
}

为什么 OrderBy 没有超载将订单方向作为参数? 在Reflector中,我发现它或多或少是在内部实现的,但由于一些奇怪的原因而没有暴露出来。

我更愿意写这样的东西:

public static IEnumerable<FileInfo> getlist(string directory, string searchPattern, string order)
{
    return new DirectoryInfo(directory)
        .EnumerateFiles(searchPattern)
        .OrderBy(f => f.CreationTime, order == "A" ? SortOrder.Ascending : SortOrder.Descending);
}

更新

我自己可以写这个,只是希望它已经在框架中了:

public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector,
    ListSortDirection order)
{
    switch (order)
    {
        case ListSortDirection.Ascending: return source.OrderBy(keySelector);
        case ListSortDirection.Descending: return source.OrderByDescending(keySelector);
    }

    throw new ArgumentOutOfRangeException("order");
}

4 个答案:

答案 0 :(得分:7)

由于SortOrder枚举在技术上可以采用超过2个值(想象(SortOrder) 35),因此它不会完全捕获二元性。有两种方法可以确保没有歧义或需要进行范围检查(你的例子btw中缺少这种方法)。

那就是说,这是你想要的方法:

public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector,
    SortOrder order)
{
    if(order < SortOrder.Ascending || order > SortOrder.Descending)
    {
        throw new ArgumentOutOfRangeException("order");
    }

    return order == SortOrder.Ascending
        ? source.OrderBy(keySelector)
        : source.OrderByDescending(keySelector);
}

答案 1 :(得分:5)

OrderBy方法已具备您需要的灵活性,以及​​更多,因为它可以采用可选的IComparer<T>参数:

return new DirectoryInfo(directory)
    .EnumerateFiles(searchPattern)
    .OrderBy(f => f.CreationTime, order == "A"
                                      ? Comparer<DateTime>.Default
                                      : new DescendingComparer<DateTime>);

// ...

public DescendingComparer<T> : Comparer<T>
{
    public override int Compare(T x, T y)
    {
        return Comparer<T>.Default.Compare(y, x);
    }
}

答案 2 :(得分:3)

我不知道为什么。虽然,在某些时候,你可以自己做。

public static class IEnumerableSortExtension
{
    public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
            this IEnumerable<TSource> source,
            Func<TSource, TKey> keySelector,
            SortOrder order)
    {
        if (order == SortOrder.Ascending)
            return this.OrderBy(keySelector);
        else if (order == SortOrder.Descending)
            return this.OrderByDescending(keySelector);
        throw new InvalidOperationException(); // do something better than this
    }
}

答案 3 :(得分:2)

其他答案比我的学术更具学术性,但如果你需要快速和肮脏,那么你可以这样做:

var files = new DirectoryInfo(directory)
               .EnumerateFiles(searchPattern)
               .OrderByDescending(f => f.CreationTime);

if (order == "A")
    files = files.Reverse();

return files;