Sorting a generic list on arbitrary property (C#)
filed in Development on Apr.14, 2009
I often need to sort a generic list on some arbitrary property. After writing the code a couple of times I decided to make it more generic using generics and some reflection. Oh, I know that reflection if costly and this is not a good way to sort large lists, but I typically work with small lists.
public enum SortDirection { Ascending, Descending } public class ListSorter where T : class { public static List Sort ( List<T> listToSort, string propertyName, SortDirection direction) where P : IComparable { Type propertyType = typeof (P); Type comparableInterface = propertyType.GetInterface("IComparable"); if (comparableInterface == null) throw new Exception("Properties to sort by must be IComparable"); listToSort.Sort( delegate(T x, T y) { PropertyInfo p1 = x.GetType().GetProperty(propertyName, propertyType); PropertyInfo p2 = y.GetType().GetProperty(propertyName, propertyType); object p1objvalue = p1.GetValue(x, null); object p2objvalue = p2.GetValue(y, null); P p1value = (P)p1objvalue; P p2value = (P)p2objvalue; if (direction == SortDirection.Ascending) return p1value.CompareTo(p2value); else return p2value.CompareTo(p1value); }); return listToSort; } } |
To sort a list of Person objects by the string property FirstName do the following:
List<Person> myUnsortedList = GetPersonsInRandomOrder(); List<Person> sortedList = ListSorter .Sort( myUnsortedList, "FirstName", SortDirection.Ascending); |
To sort a list of Person objects by the int property Age do the following:
List<Person> myUnsortedList = GetPersonsInRandomOrder(); List<Person> sortedList = ListSorter .Sort( myUnsortedList, "Age", SortDirection.Ascending); |
If you have the luxury of using .NET Framework 3.0 or 3.5 you can use Linq to solve the problem really quick:
var sortedPersonList = from p in unsortedPersonList orderby p.FirstName select p; foreach (var person in sortedPersonList) { Console.WriteLine(person.FirstName + " " + person.LastName); } |
Leave a comment to this post if you have any thoughts.
April 23rd, 2009 on 20:27
Hi Pal,
You are the best! was searching for generic list sort in a simple way, and no one mentioned about Linq !
Thanks again, it save me a big chunk of code and Thanks to Linq’s Simplicity…
Thanks,
Gopi
April 23rd, 2009 on 21:29
Yes, Linq is really handy and I use it more and more in different places I had not thought of at first.
August 7th, 2009 on 00:26
Awesome code Pal
!!! , very, very useful.. just searching for some like this.. thank you a lot!!!
Regards
August 15th, 2009 on 22:55
This works well for properties that are ints, dates, etc. But what about for a string property where the value could contain special characters? In particular, I’m pretty sure values like “coop” and “co-op” would be sorted together by the default CompareTo for strings in this code. Short of doing some kind of ugly if-then-else in the delegate, how can this be made to use the ordinal type of string compare?
August 21st, 2009 on 12:24
Good question. You’ll have to test that and let us know