Click here to Skip to main content
13,350,486 members (77,202 online)
Click here to Skip to main content
Add your own
alternative version


24 bookmarked
Posted 2 Nov 2010

Custom Sort a List of Objects by Any Order

, 14 Mar 2012
Rate this:
Please Sign up or sign in to vote.
An IList Extension Method that sorts the list in any order or in a combination of orders.


Recently, I encountered a problem at my work - a list of account objects needed to appear in a specific order in a report and the order had to look like:

  • ISA Stock 
  • ISA Cash 
  • Wrap Cash 
  • Personal Portfolio 

The order is by the Account object's AccountType property. Apparently, I cannot use the IEnumerable.OrderBy() method as the order required is not alphabetical. I could add an extra property - Order - to the Account object so that ISA Stock accounts will have Order = 1; ISA Cash accounts have Order = 2, etc, then sort the accounts by Order property. But I don't like the idea of bloating my class just for sorting. Besides, in a different scenario, the order may differ.

Another possible solution is to make the Account class implement the IComparable interface, but again, the order may be different for different scenarios, and implementing IComparable can only deal with one specific order. Besides, sometimes you may not have access to modify the class you want to sort. So a better solution would be to separate the sorting algorithm from the objects you want to sort. In this way, they both can vary independently - a cliche in the GoF Design Pattern book :)  

So I ended up developing an IList Extension Method and a Sorter class which mimics the syntax of IEnumerable.OrderBy() and lets you custom sort (rather than alphabetical) a list of objects by its string or enum properties. (Contrary to common belief, my Sorter class doesn't implement the IComparer interface for reasons I will discuss later.) 

Download the Source Code  

Thanks to Paw Jershauge for pointing out the source code download location:   

How to Use CustomSort 

To sort a list by a single property: 

_listToBeSorted.Sort(x => x.AccountType, "ISA Stock,ISA Cash,Wrap Cash,Personal Portfolio");

you can specify a StringComparison to control how strings are compared when doing the sort:

_listToBeSorted.Sort(x => x.AccountType, "ISA Stock,ISA Cash,Wrap Cash,Personal Portfolio", 

If you want to sort by more than one property, you have to use the Sorter class. I employed the Fluent Interface technique to make the code more readable:

var sorter = new Sorter<ClassToBeSorted, string>(); 

    sorter.Add(x => x.AccountType, "ISA Stock,ISA Cash,Wrap Cash,Personal Portfolio") 
          .Add(x => x.AccountName, "Peter,Adam", StringComparison.InvariantCultureIgnoreCase)
          .Add(x => x.AccountLocation, "London,Edinburgh") 

If your object contains other objects as properties, for example:

public class CompositeClassToBeSorted { 
   public ClassToBeSorted ClassProperty; 
   public string ClassName; 

you can drill down as deep as you want to use a certain property for sorting:

_listToBeSorted.Sort(x => x.ClassProperty.AccountType, "Wrap,Cash");

The IEnumerable.OrderBy() method have the same capability but it doesn't sort correctly if the to-be-sorted object property is a collection of other objects and you want to sort by a certain element in the collection. For example, if you have a class like this:

public class ListClass
    public List<ClassToBeSorted> ClassProperty;

the following won't work:

_listToBeSorted.OrderBy(x => x.ClassProperty[3].AccountType);

However, you can use my custom sorter to sort by certain elements in a property of List type:

classList.Sort(x => x.ClassProperty[0].AccountType, "Wrap,Cash");

The Sorting Behaviour, Implementation, and Performance 

If your whole list contains A, B, C, D, E, F, and you only specify partial order, i.e.:

_listToBeSorted.OrderBy(x => x.AccountType,"B,E"); 

then B, E will come on top of the list, and the rest of the elements will remain where they are.

Initially, I made CustomSort to implement the IComparer interface and use the IList.Sort(IComparer) method to sort the list. It works like a charm if the custom sort order contains every element in the list. But when we only specify a partial order, the remaining elements don't stay where they are, but kind of randomised (or maybe, there is a pattern that I failed to see). So I ended up sorting the list myself.

The performance could be better. I tested it with a list of 1000 objects. If the sort is only by one property, sorting completes in a split second. But if you sort by two or three properties, the sort will take a few seconds. I have included a performance test in the attached source file. You can see for yourself whether the performance is satisfactory for you.

Possible Improvements

  1. At the moment, the custom sort only works for the generic IList. It is easy enough to do the same for IEnumerable. It is just that I found IList to be the most common collection, and you can convert IEnumerable to List easily by calling the ToList() method.
  2. The custom sort can sort by a property which is a List, classList.Sort(x => x.ClassProperty[0].AccountType, "Wrap,Cash"), but it doesn't do so for Dictionary type properties. Again, this can be easily achieved.
  3. Performance can be improved, but I haven't been bothered to try out various sorting algorithms. I just did enough to satisfy the requirement of my own work situation.

About the Source Code and Unit Tests 

The source code is in .NET 3.5. Some of the .NET 4.0 features, like optional parameters, dynamics, etc., will make the code more concise and maybe more efficient, but for better backwards compatibility, I stuck to .NET 3.5 for now. The project file should open and convert fine in VS2010 (I tested and it works). I will aim to provide a copy of the source code in .Net 4.0 soon.  

The tests are written in xunit in a Behaviour Driven Development (BDD) style. When executed in ReSharper, it gives the nice documentation-like specs. To run the tests, your reSharper needs to have the xunit test runner plugin installed.  



This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Team Leader XYZ Studios Ltd
China China
I am an independent IT contractor who is passionate about life and Microsoft technology stack. I have been programming since 2001. Besides coding, I also enjoy diving, swimming, rock climbing and travelling. I swim 2 miles a day to keep my morale and energy level consistently high.

You may also be interested in...

Comments and Discussions

QuestionAlternate solution Pin
James Jegers11-Oct-17 10:03
memberJames Jegers11-Oct-17 10:03 
QuestionSource code no longer available :-( Pin
Stefan Rehnberg10-Jun-16 0:08
memberStefan Rehnberg10-Jun-16 0:08 
AnswerRe: Source code no longer available :-( Pin
James Jegers11-Oct-17 10:01
memberJames Jegers11-Oct-17 10:01 
General[My vote of 1] Incomplete Pin
kevininstructor18-Jul-14 17:36
memberkevininstructor18-Jul-14 17:36 
GeneralRe: [My vote of 1] Incomplete Pin
Bassam Abdul-Baki26-Sep-14 2:55
professionalBassam Abdul-Baki26-Sep-14 2:55 
QuestionSource Code..(??) Pin
_Marshall26-Apr-13 10:48
member_Marshall26-Apr-13 10:48 
QuestionNice work. Suggestion for improving performance. Pin
aranda12-Mar-12 17:00
memberaranda12-Mar-12 17:00 
Inside ReflectionHelper you can cache the results of Type.GetMethod(), Type.GetField() and Type.GetProperty() (These methods are very slow and will be called a lot of times with the same parameters). You could store them in dictionaries keyed by the Type and the member name.

To be honest I haven't tried it myself yet as CustomSorterSpecifications crashed (auto upgraded to VS2010). It's possible that these calls internally cache their results, but in previous .Net version I've seen very significant performance increases by doing this.
GeneralSuggestion... Pin
Andrew Rissing9-Nov-10 6:21
memberAndrew Rissing9-Nov-10 6:21 
GeneralOne (silly?) question: Where can I download the sourcecode? [modified] Pin
Florian.Witteler9-Nov-10 2:16
memberFlorian.Witteler9-Nov-10 2:16 
AnswerRe: One (silly?) question: Where can I download the sourcecode? [modified] Pin
Paw Jershauge12-Mar-12 4:13
memberPaw Jershauge12-Mar-12 4:13 
GeneralMy vote of 5 Pin
John Brett3-Nov-10 0:27
memberJohn Brett3-Nov-10 0:27 
GeneralMy vote of 5 Pin
jim lahey2-Nov-10 23:49
memberjim lahey2-Nov-10 23:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.180111.1 | Last Updated 14 Mar 2012
Article Copyright 2010 by Frank_Zh
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid