2010-07-14 23 views
4

目前,如果我們得到有序的方向作爲外部的依賴,我們必須使用如果應用此方向:爲什麼有OrderBy和OrderByDescending但不是OrderBy(SortOrder)?

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

爲什麼沒有排序依據的重載需要爲了方向作爲參數? 在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"); 
} 

回答

7

由於SortOrder枚舉在技術上可以具有超過2個值(認爲是(SortOrder) 35),因此它不會完全捕獲二元性。有2種方法可以確保不存在歧義或需要進行範圍檢查(這在您的示例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

+1:正是我要說的。 – 2010-07-14 21:40:40

+0

感謝代碼,這不是重點。順便說一句,代碼將更加漂亮開關。 – 2010-07-14 22:01:09

+0

爲了捕獲雙重性,您可以使用bool,但這會降低可讀性。 – 2010-07-14 22:08:52

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

這是一個很好的! – 2010-07-15 04:13:13

+0

@Konstantin:當然,如果你發現你需要額外的比較策略,而不是簡單的asc或desc,那麼你可以簡單地創建一個合適的比較器。 – LukeH 2010-07-15 12:59:45

2

其他的答案比我更學術,但如果你需要快速和骯髒,那麼你可以這樣做:

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

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

return files;