2009-01-27 24 views
6

Ok vì vậy tôi có một số phương pháp mà trông như thế này: - mà sắp xếp một danh sách của nghệ sĩ, album, năm, vvTránh mã lặp lại khi sử dụng 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(); 
     } 

và điều này:

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

Bây giờ rõ ràng đây không phải là mã tốt vì vậy nó cần tái cấu trúc thành một phương thức Sort() nhưng tôi không thể tìm ra cách để làm điều đó theo cách đơn giản nhất có thể. Tôi không quan tâm nếu nó sử dụng IComparer hoặc LINQ.

Tôi muốn nó giống như thế này:

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

    public enum SortType 
    { 
     Artist, 
     Album, 
     Year 
    } 

Vì vậy, whats cách sạch nhất để làm điều này không có mã lặp lại?

Cảm ơn, Lee

Trả lời

12

Bạn sẽ có thể mimick chữ ký của phương pháp khuyến nông OrderBy:

Cập nhật 1 bạn phải rõ ràng trong tham số generic đầu tiên keySelector Func của bạn. Tôi sẽ đoán về kiểu của bạn và gọi nó là "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(); 
    } 
} 

Bây giờ bạn có thể gọi là "Phân loại" như thế này:

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

Cập nhật 2

Theo dõi trên bình luận Tom Lokhorst của: Nếu bạn muốn ấn định trước một số tiêu chí phân loại tốc ký, bạn có thể làm như vậy bằng cách xác định một lớp học như sau:

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

Bây giờ bạn có thể chỉ cần gọi:

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

Ngoài ra, nếu bạn, vì một lý do nào đó, không muốn viết xuống lambda rõ ràng trong lệnh gọi 'Sort' (nó coul d nhận được lớn), bạn có thể tạo một số loại danh sách với các đối tượng 'Func ' được xác định trước (tương đương với enum trong ví dụ). –

+0

Hài hước Tôi đọc rằng chỉ sáng nay trong cuốn sách LINQ trong Hành động –

+0

Các đối số kiểu cho phương thức 'System.Linq.Enumerable.OrderByDescending (System.Collections.Generic.IEnumerable , System.Func ) 'không thể suy ra từ việc sử dụng. Hãy thử xác định các đối số kiểu một cách rõ ràng. Trên các đơn đặt hàng và orderbyDesc dòng. –

0

Âm thanh như sắp xếp đang tự tạo một cuộc sống nếu bạn có một số phương pháp dành riêng cho nó. Có lẽ chúng có thể được tập hợp thành một lớp.

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

Dưới đây là cách sử dụng mẫu:

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

Output là Paul, John, Ringo, George.

0

Tôi nghĩ bạn nên thêm một phương pháp khuyến nông để 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(); 
      } 
    } 
} 

và sau đó bạn có thể sử dụng khá với tất cả các đối tượng của bạn:

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 đã tồn tại:

using System.Data.SqlClient; 
Các vấn đề liên quan