Sorting a .Net list with lambdas

I love linq.  I would wager that most developers who have done much with it share a similar love.

It makes our lives easier.  It eliminates writing copies amounts of loops, parsing xml, interacting with databases, you name it.  It’s great.

When I run into a situation where linq does not have an obvious tie in, I start to get a little anxious,  (pathetic I realize).

Today I was faced with a situation where I had a list of custom classes that I needed to sort. 

This being a list, OrderBy was nowhere to be found.

So, I returned to my roots and started writing a compare for my class so that I could use the Sort command that is part of the List generic type.  That is when it struck me that I could probably accomplish this using a lambda.  It turns out that I was correct.  Lambda’s were a perfect fit for this scenario.  The code remained clean and concise and I was saved having to write additional methods just to accomplish a one-off scenario on what was a otherwise complete project.

Lamdas are a progression in C# past anonymous methods.  In the code below, I show how the code would be implemented with separate function, an anonymous method and finally, with a Lambda expression.

First, the test class that we’ll be working with:

public class MyClass
{
    public int propA { get; set; }
    public int propB { get; set; }
    public int propC { get; set; }
}

Our test class:

public class Tester
{
    public void Main()
    {
        List list = new List();
        list.Add(new MyClass() { propA = 1, propB = 2, propC = 3 });
        list.Add(new MyClass() { propA = 2, propB = 3, propC = 4 });
        list.Add(new MyClass() { propA = 3, propB = 4, propC = 5 });
        list.Add(new MyClass() { propA = 4, propB = 5, propC = 6 });        
    }
}

Now then, we write a custom comparer.  Not a lotof code, but you can imagine how this extrapolates over various properties for large classes.

public class Tester
{
    private static int CompareByPropA(MyClass a, MyClass b)
    {
        return a.propA.CompareTo(b.propA);
    }
    public void Main()
    {
        List list = new List();
        list.Add(new MyClass() { propA = 1, propB = 2, propC = 3 });
        list.Add(new MyClass() { propA = 2, propB = 3, propC = 4 });
        list.Add(new MyClass() { propA = 3, propB = 4, propC = 5 });
        list.Add(new MyClass() { propA = 4, propB = 5, propC = 6 });

        //Using the comparer built into the MyClass method
        list.Sort(CompareByPropA);        
    }
}

This time, we drop the custom comparer and implement the sort using an anonymous method.

public class Tester
{
    public void Main()
    {
        List list = new List();
        list.Add(new MyClass() { propA = 1, propB = 2, propC = 3 });
        list.Add(new MyClass() { propA = 2, propB = 3, propC = 4 });
        list.Add(new MyClass() { propA = 3, propB = 4, propC = 5 });
        list.Add(new MyClass() { propA = 4, propB = 5, propC = 6 });

        //Using an anonymous method
        list.Sort(delegate(MyClass a, MyClass b) { return a.propA.CompareTo(b.propA); });
    }
}

Finally, we rewrite the anonymous method into a Lambda.  It is still easy to read and much more concise.

public class Tester
{
    public void Main()
    {
        List list = new List();
        list.Add(new MyClass() { propA = 1, propB = 2, propC = 3 });
        list.Add(new MyClass() { propA = 2, propB = 3, propC = 4 });
        list.Add(new MyClass() { propA = 3, propB = 4, propC = 5 });
        list.Add(new MyClass() { propA = 4, propB = 5, propC = 6 });

        //Using a Lambda
        list.Sort((a, b) => a.propA.CompareTo(b.propA));
    }
}

So, next time you go to write custom compare code, step back and see if you can do it a little more simply.  If you are going to be using your comparison code in more than one place, then perhaps it is still a better idea to implement it using that route vs the lambda.  If it is a one-off thing, then a lambda and some linq can be a beautiful thing!

Posted in .Net c#

Categories

Archives