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

12 Comments

Comments have been disabled for this content.