C# collection sorting tip: using lambda expression when you call the Sort() method

Posted: (EET/GMT+2)

 

This time, I'm posting a simple collection sorting tip, which is useful if you have a generic list of classes you've designed for your application's needs. Say, you have this class:

public class ItemData
{
    public string Name { get; set; }
    public DateTime CreatedAt { get; set; }
}

Now, if you have a list of such items, and wanted to sort them by date, how would you do this easily? The List class has a nice Sort method, but it doesn't directly understand custom class types, and thus you need to write some code to implement the sorting. If you have used LINQ, you might already know about the solution: use the OrderBy extension method:

IEnumerable sorted = unsorted.OrderBy(i => i.CreatedAt);

However, sometimes the OrderBy method is not available, and/or you might have other reasons to call the Sort method instead. The Sort method does not accept a Func parameter, but instead takes something called a Comparison parameter.

The question is, how is such a parameter given? If you try to use the Sort method with a similar parameter than the OrderBy example above, then you will get an error message that says:

Cannot convert lambda expression to type
'System.Collections.Generic.IComparer' because
it is not a delegate type.

The solution is to first define a Comparison object, and then pass that as a parameter to the Sort method. Here's how:

Solution:

Comparison createdDateAscending =
    (a, b) => a.CreatedAt.CompareTo(b.CreatedAt);
unsorted.Sort(createdDateAscending);

Here is the complete code (a C# console application):

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

namespace SortingTest
{
    public class ItemData
    {
        public string Name { get; set; }
        public DateTime CreatedAt { get; set; }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            List unsorted = new List() {
                new ItemData() {
                    Name = "CCCC",
                    CreatedAt = DateTime.Now.AddMinutes(-15)
                },
                new ItemData() {
                    Name = "BBBB",
                    CreatedAt = DateTime.Now.AddMinutes(-10)
                },
                new ItemData() {
                    Name = "AAAA",
                    CreatedAt = DateTime.Now.AddMinutes(-5)
                }
            };

            // the LINQ way
            IEnumerable sorted = unsorted.OrderBy(i => i.CreatedAt);

            // using the Sort method
            Comparison createdDateAscending =
                    (a, b) => a.CreatedAt.CompareTo(b.CreatedAt);
            unsorted.Sort(createdDateAscending);

            // descending sort: reverse A and B
            Comparison createdDateDescending =
                    (a, b) => b.CreatedAt.CompareTo(a.CreatedAt);
            unsorted.Sort(createdDateDescending);
        }
    }
}

Notice how there's an example on how to use the Sort and the Comparison object for both ascending and descending sorting. Hope this helps!