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 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 myUnsortedList = GetPersonsInRandomOrder();
List sortedList = ListSorter
.Sort(
myUnsortedList,
"FirstName",
SortDirection.Ascending);
To sort a list of Person objects by the int property Age do the following:
List myUnsortedList = GetPersonsInRandomOrder();
List 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.
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
Yes, Linq is really handy and I use it more and more in different places I had not thought of at first.
Awesome code Pal
!!! , very, very useful.. just searching for some like this.. thank you a lot!!!
Regards
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?
Good question. You’ll have to test that and let us know