Implementing Sorting in Generic List (List<T>)

How to sort a generic list? Well, generic list provides a sort method itself in the form List<T>.Sort(). But wait a sec. This method requires you to implement sorting mechanism in your type. This is because this method uses default sorting mechanism. This is really simple, but what if you don't have sorting mechanism in your type? In that case this method throws InvalidOperationExpression.

List<T>.Sort() method uses the default comparer Comparer(T).Default for type T to determine the order of list elements. The Comparer(T).Default property checks whether type T implements the IComparable(T) generic interface and uses that implementation, if available. If not, Comparer(T).Default checks whether type T implements the IComparable interface. If type T does not implement either interface, Comparer(T).Default throws an InvalidOperationException.

If you use system types like String, default comparer works fine. This is because String class implements IComparable interface. If you see the definition of String class, it looks like (you can see this by pressing F12 keeping the cursor on the word 'String' in the code editor of visual studio):

public sealed class String : IComparable, ICloneable, IConvertible, 
                             IComparable<string>, IEnumerable<char>, 
                             IEnumerable, IEquatable<string> 
 

But for types that does not implement Icomparable, default sort does not work. However there is one work around. This trick uses delegates.

To illustrate this example, I created a simple class Post. The code of this class is as below. This class does not implement IComparable interface. So default sort will not work for this.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Tyagi.Utility
{
    public class Post : IComparable<Post>
    {
        public String Title { get; set; }
        public String Source { get; set; }
    }
}

Create another class that will consume this class.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Tyagi.Utility
{
    public class PostsList
    {
        List<Post> posts = new List<Post>();

        public List<Post> GelPosts()
        {
            posts.Add(new Post { Title = "MSN Space", Source = "Blog" });
            posts.Add(new Post { Title = "CNBC TV 18", Source = "News" });
            posts.Add(new Post { Title = "Independence Day", Source = "Movie" });

            posts.Sort(delegate(Post P1, Post P2)
            {
                return P1.Title.CompareTo(P2.Title);
            });

            return posts;
        }
        
        
    }
}

The trick is in the use of a delegate in the call to Sort method of the posts object.

posts.Sort(delegate(Post P1, Post P2)
{
    return P1.Title.CompareTo(P2.Title);
});

The delegate accepts two parameter, both of the same class Post. It the uses the CompareTo method. This method is defined in the type of property. In this example, Title property of Post class is of type string. So the CompareTo method of string class will be called in this case. CompareTo method returns int. Sort method of List<T> uses this integer to compare two objects.

The above code returns list in the ascending order of title. To reverse the order, simply reverse the code as be below:

posts.Sort(delegate(Post P1, Post P2)
{
    return P2.Title.CompareTo(P1.Title);
});

 

This is one way. You can implement the sorting functionality in your class as well. I will discuss this in the next post.

kick it on DotNetKicks.com

Published Tuesday, January 27, 2009 2:19 PM by Yanesh Tyagi
Filed under: , ,

Comments

# re: Implementing Sorting in Generic List (List<T>)

Tuesday, January 27, 2009 3:57 AM by Shay Jacoby

I would use lambda expressions like this:

posts.Sort((x, y) => string.Compare(x.Title, y.Title));

# re: Implementing Sorting in Generic List (List<T>)

Tuesday, January 27, 2009 7:45 AM by derikwhittaker

You could also just use the linq extension OrderBy and save yourself a bit of trouble of having to create a compare object.  However, if you need fancy sorting then the linq extension may not be the right way to go.

# re: Implementing Sorting in Generic List (List<T>)

Tuesday, January 27, 2009 8:57 AM by Joe Chung

LINQ would be fine for "fancy" sorting.  see Shay's comment and replace .Sort with .OrderBy/.OrderByDescending.

# re: Implementing Sorting in Generic List (List<T>)

Wednesday, January 28, 2009 3:03 AM by Yanesh Tyagi

@Shay

Cool.. This will make code more readable. Thanks :)

@derikwhittaker

Linq extension orderby can be used only with the linq queries. Here I am talking about sorting the generic list. Anyways, thanks for sharing your thoughts.

# re: Implementing Sorting in Generic List (List<T>)

Wednesday, January 28, 2009 4:20 PM by Niki

"Linq extension orderby can be used only with the linq queries. Here I am talking about sorting the generic list. Anyways, thanks for sharing your thoughts."

Who says that? The Enumerable.OrderBy extension method works on any IEnumerable<T>, that includes List<T>.

# re: Implementing Sorting in Generic List (List<T>)

Thursday, July 30, 2009 12:37 PM by Jason Plank

Your example class "Post" implements IComparable in the write-up.  It's a bit confusing.

# re: Implementing Sorting in Generic List (List<T>)

Monday, March 1, 2010 3:22 AM by Rajan

above example is very useful for me.

# re: Implementing Sorting in Generic List (List<T>)

Tuesday, May 4, 2010 10:01 AM by Prem

This really helped me to fix my issue with sorting.

kudos to you !!!...........

# re: Implementing Sorting in Generic List (List<T>)

Sunday, May 23, 2010 3:25 AM by Adam Kim

I don't think you meant to derive class Post from  IComparable<Post>.  The way it is, you can't even get this to compile since you don't implement CompareTo.

# re: Implementing Sorting in Generic List (List<T>)

Monday, February 7, 2011 5:07 AM by Anup Pandey

Nice Code!! Thanks

# re: Implementing Sorting in Generic List (List<T>)

Friday, March 18, 2011 2:11 AM by Rahan

bad code.....Not fill my expectation

# re: Implementing Sorting in Generic List (List<T>)

Wednesday, November 2, 2011 5:11 AM by thawzinlatt

how can I sort using two property ? first will be sort with ID , if ID is equal then sort with name.