2010-07-14 5 views
4

Actuellement, si nous obtenons la direction de la commande en tant que dépendance externe, nous devons utiliser si pour appliquer cette direction:Pourquoi OrderBy et OrderByDescending, mais pas 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); 
} 

Pourquoi est-il pas de surcharge de OrderBy qui prend la direction de l'ordre en tant que paramètre? Dans Reflector, je vois qu'il est plus ou moins implémenté en interne mais pas exposé pour une raison étrange.

Je préférerais préfère écrire quelque chose comme ceci:

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

Mise à jour:

Je peux écrire moi-même, juste espérait que c'est déjà dans le cadre:

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

Répondre

7

Comme une énumération SortOrder peut techniquement prendre plus de 2 valeurs (pensez (SortOrder) 35), elle ne capturerait pas exactement la dualité. Avoir 2 méthodes assure qu'il n'y a pas d'ambiguïté ou de besoin de vérification de gamme (ce qui manque dans votre exemple btw).

Cela dit, voici la méthode que vous voulez:

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: Exactement ce que j'allais dire. –

+0

Merci pour le code, ce n'est pas le point. Btw, le code sera beaucoup plus joli avec le commutateur. –

+0

Pour capturer la dualité, vous pouvez utiliser bool mais cela diminuera la lisibilité. –

3

Je ne sais pas pourquoi. Bien que, dans le moment, vous pouvez le faire vous-même.

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

La méthode OrderBy a déjà la flexibilité dont vous avez besoin, et plus, car il peut prendre un argument IComparer<T> en option:

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

C'est un bon! –

+0

@Konstantin: Et, bien sûr, si vous avez trouvé que vous aviez besoin de stratégies de comparaison supplémentaires autres que plain asc ou desc, alors vous pourriez simplement créer un comparateur approprié. – LukeH

2

Les autres réponses sont plus académiques que le mien, mais si vous avez besoin rapide et sale, alors vous pouvez le faire:

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

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

return files;