Sorting items in a database using SQL is easy, simply order by whatever field you want that supports sorting, its easy to take that power for granted. But what if you already have your data in the form of a generic object collection which you want to sort.
It turns out to be quite simple, all you need to do is create a collection of
System.Collections.Generic.List and call the Sort() method. This will sort the collection by the item's
System.IComparable interface. I have for this example created a simple class of type Item with a few properties. Take a look at the method
int IComparable.CompareTo(object obj) in my class. When the Sort method is called on the collection it will be sorted alphabetically a-z on the
Title property. Quite simple really, only what if you want to reorder your collection ordering by the
CreatedDate property say in descending order?
| public class Item : IComparable |
| { |
| public int ID { get; set; } |
| public string Title { get; set; } |
| public DateTime CreatedDate { get; set; } |
| |
| int IComparable.CompareTo(object obj) |
| { |
| if ((obj == null) || (obj.GetType() != GetType())) |
| { |
| return -1; |
| } |
| Item castObj = (Item)obj; |
| return Title.CompareTo(castObj.Title); |
| } |
| } |
Implement a IComparer class
Create a ItemComparer class that inherits from the generic IComparer class and implement the method int IComparer- .Compare(Item x, Item y)
. You can see in the example below I have created a Field and SortDirection enum. I prefer this approach to passing a string value, particularly if someone else is going to use your class.
public sealed class ItemComparer : IComparer-
|
| { |
| public enum SortDirection |
| { |
| Ascending = 0, |
| Descending = 1 |
| } |
| |
| public enum Field |
| { |
| ID, |
| Title, |
| CreatedDate |
| } |
| |
| private readonly Field _field = Field.Title; |
| private readonly SortDirection _sortDirection = SortDirection.Ascending; |
| |
| public ItemComparer(Field field, SortDirection sortDirection) |
| { |
| _field = field; |
| _sortDirection = sortDirection; |
| } |
| |
int IComparer- .Compare(Item x, Item y)
|
| { |
| if (_sortDirection == SortDirection.Ascending) |
| { |
| switch (_field) |
| { |
| case Field.Title: |
| return string.Compare(x.Title, y.Title); |
| case Field.CreatedDate: |
| return DateTime.Compare(x.CreatedDate, y.CreatedDate); |
| case Field.ID: |
| return x.ID.CompareTo(y.ID); |
| default: |
| goto case Field.Title; |
| } |
| } |
| switch (_field) |
| { |
| case Field.Title: |
| return string.Compare(y.Title, x.Title); |
| case Field.CreatedDate: |
| return DateTime.Compare(y.CreatedDate, x.CreatedDate); |
| case Field.ID: |
| return y.ID.CompareTo(x.ID); |
| default: |
| goto case Field.Title; |
| } |
| } |
| } |
Sort the Generic Collection using IComparer
Great now I have an item IComparer class and can choose which field to sort by and the sort order.
List- items =
new List- ();
|
| items.Add(new Item { ID = 1, CreatedDate = DateTime.Now, Title = "Title 1" }); |
| items.Add(new Item { ID = 2, CreatedDate = DateTime.Now, Title = "Title 2" }); |
| items.Add(new Item { ID = 3, CreatedDate = DateTime.Now, Title = "Title 3" }); |
| items.Sort(new ItemComparer(ItemComparer.Field.CreatedDate, ItemComparer.SortDirection.Descending)); |
So you can see it is quite straight forward to sort you collection dynamically on different properties of your class.