2009-01-27 11 views
6

好時候,所以我有一些方法,看起來像這樣避免重複的代碼 - 它通過藝術家,專輯,年份等使用LINQ

 public void SortByAlbum(SortOrder sortOrder) 
     { 
      if (sortOrder == SortOrder.Ascending) 
       _list = _list.OrderBy(x => x.Album).ToList(); 
      else if (sortOrder == SortOrder.Descending) 
       _list = _list.OrderByDescending(x => x.Album).ToList(); 
     } 

這個排序列表:

 public void SortByArtist(SortOrder sortOrder) 
     { 
      if (sortOrder == SortOrder.Ascending) 
       _list = _list.OrderBy(x => x.Artist).ToList(); 
      else if (sortOrder == SortOrder.Descending) 
       _list = _list.OrderByDescending(x => x.Artist).ToList(); 
     } 

現在顯然這是不好的代碼,所以它需要重構成一個Sort()方法,但我不知道如何以最簡單的方式來完成它。我不在乎它是否使用IComparer或LINQ。

我希望它看起來是這樣的:

public void Sort(SortOrder sortOrder, SortType sortType) 
    { 
     //implementation here 
    } 

    public enum SortType 
    { 
     Artist, 
     Album, 
     Year 
    } 

所以什麼沒有代碼重複做這個最乾淨的方式是什麼?

感謝,李

回答

12

你應該能夠模擬天生的排序依據擴展方法的簽名:

更新1你必須在第一個泛型參數到您的KeySelectors Func鍵明確。我會猜測你的類型並稱之爲「Song」。

public void Sort<TKey>(SortOrder sortOrder, 
         Func<Song, TKey> keySelector) 
{ 
    if (sortOrder == SortOrder.Descending) 
    { 
     _list = _list.OrderByDescending(keySelector).ToList(); 
    } 
    else 
    { 
     _list = _list.OrderBy(keySelector).ToList(); 
    } 
} 

現在你可以稱之爲 「排序」 是這樣的:

Sort(SortOrder.Descending, x => x.Album); 

更新2

湯姆Lokhorst的評論跟進:如果你想預先設置一些速記排序條件,可以通過定義這樣的類來實現:

public static class SortColumn 
{ 
    public static readonly Func<Song, string> Artist = x => x.Artist; 
    public static readonly Func<Song, string> Album = x => x.Album; 
} 

現在您只需致電:

Sort(SortOrder.Descending, SortColumn.Artist); 
+0

另外,如果你出於某種原因,不想在調用`Sort`時寫下明確的lambda表達式, d get big),你可以用預定義的`Func `對象(相當於示例中的enum)創建某種列表。 – 2009-01-27 22:31:22

0

聽起來像分揀正在對自己的生活,如果你有專門給它的幾種方法。也許他們可以聚集成一個班級。

public enum SortOrder 
{ 
    Ascending = 0, 
    Descending = 1 
} 
public class Sorter<T> 
{ 
    public SortOrder Direction { get; set; } 
    public Func<T, object> Target { get; set; } 
    public Sorter<T> NextSort { get; set; } 

    public IOrderedEnumerable<T> ApplySorting(IEnumerable<T> source) 
    { 
     IOrderedEnumerable<T> result = Direction == SortOrder.Descending ? 
      source.OrderByDescending(Target) : 
      source.OrderBy(Target); 

     if (NextSort != null) 
     { 
      result = NextSort.ApplyNextSorting(result); 
     } 
     return result; 
    } 

    private IOrderedEnumerable<T> ApplyNextSorting 
     (IOrderedEnumerable<T> source) 
    { 
     IOrderedEnumerable<T> result = Direction == SortOrder.Descending ? 
      source.ThenByDescending(Target) : 
      source.ThenBy(Target); 
     return result; 
    } 
} 

這裏的示例用法:

List<string> source = new List<string>() 
    { "John", "Paul", "George", "Ringo" }; 

Sorter<string> mySorter = new Sorter<string>() 
{ 
    Target = s => s.Length, 
    NextSort = new Sorter<string>() 
    { 
     Direction = SortOrder.Descending, 
     Target = s => s 
    } 
}; 

foreach (string s in mySorter.ApplySorting(source)) 
{ 
    Console.WriteLine(s); 
} 

輸出是保羅,約翰,林檎,喬治。

0

我想你應該添加一個擴展方法IList<T>

public static class extIList { 
    public static IList<T> Sort<T, TKey>(this IList<T> list, SortOrder sortOrder, Func<T, TKey> keySelector) { 
      if (sortOrder == SortOrder.Descending) { 
       return list.OrderByDescending(keySelector).ToList(); 
      } else { 
       return list.OrderBy(keySelector).ToList(); 
      } 
    } 
} 

,然後你可以用每一個你的對象相當使用:

IList<Person> list = new List<Person>(); 

list.Add(new Person("David","Beckham")); 
list.Add(new Person("Gennaro","Gattuso")); 
list.Add(new Person("Cristian","Carlesso")); 

list = list.Sort(SortOrder.Descending, X => X.Name); 

PS SortOrder的已經存在:

using System.Data.SqlClient;