The other day I had come across a problem. I needed to be able to sort one of my generic lists by several different properties.
Let us take the following code:
class Program { static void Main(string[] args) { var myList = new List<MyObject> { new MyObject{SortId = "D"}, new MyObject{SortId = "B"}, new MyObject{SortId = "C"}, new MyObject{SortId = "A"} }; foreach (MyObject o in myList) { Console.WriteLine(o.SortId); } Console.ReadLine(); } } class MyObject { public string SortId { get; set; } }
If you run this code you will see the following output:
So, we want to be able to sort this list.
The way this is normally done is like this:
myList.Sort((s1, s2) => s1.SortId.CompareTo(s2.SortId));
If you add this little bit of code right before your foreach statement you get the following output:
This works great. Now, we want to add a new property to our object. Let’s call is Value for simplicity.
Here is our new object:
class MyObject { public string SortId { get; set; } public string Value { get; set; } }
We are now going to update or object initialization with the new property:
var myList = new List<MyObject> { new MyObject{SortId = "D", Value = "Value1"}, new MyObject{SortId = "B", Value = "Value3"}, new MyObject{SortId = "C", Value = "Value4"}, new MyObject{SortId = "A", Value = "Value2"} };
So, now we want to sort of the Value column or the SortId column.
Normally we would just add an if statement based on some parameters on which one we wanted to sort by.
Something like this (yes, this would be done a lot better if we were to pursue this avenue):
string sortBy = "Value"; if (sortBy == "SortId") { myList.Sort((s1, s2) => s1.SortId.CompareTo(s2.SortId)); } else { myList.Sort((s1, s2) => s1.Value.CompareTo(s2.Value)); }
So, how are we going to write our sorting without all these giant If() statements in our code? I want to avoid as much code in my business logic as possible. Especially when it comes to doing if() statements.
Let’s look at the Func<,> method in c#
I am not going to go into detail on what Func really is, you can read up on it here: MSDN : Func
We are going to create an extension methos off of MyObject. This extension method will allow us to call the .Sort() directly from our object.
Let’s take a look at our method. This is the complete method which does the sort.
public static class ObjectExtension { public static List<MyObject> Sort<T>(this List<MyObject> o , Func<MyObject, T> keySort) where T : IComparable { o.Sort((a, b) => keySort(a).CompareTo(keySort(b))); return o; } }
So what is happening here?
We are passing in an expression (func) which will extract the value which will be used to compare. You add the constraint where T: IComparable to allow the expression to be compared. If you do not have this you will get a compile error saying that CompareTo does not exist.
Okay, so how do I call something like this?
First, before we continue, make sure you make your MyObject class public, so your extension method will work.
public class MyObject { public string SortId { get; set; } public string Value { get; set; } }
Now, we are going to update our program to call the extension method. We will have the same object initialization the only difference is we will be calling our extension method to do the sort.
static void Main(string[] args) { var myList = new List<MyObject> { new MyObject{SortId = "D", Value = "Value1"}, new MyObject{SortId = "B", Value = "Value3"}, new MyObject{SortId = "C", Value = "Value4"}, new MyObject{SortId = "A", Value = "Value2"} }; myList.Sort(myObject => myObject.Value); foreach (MyObject o in myList) { Console.WriteLine(o.SortId + " - " + o.Value); } Console.ReadLine(); }
As you can see we are calling myList.Sort() but this time we are using an expression to say, use this property to sort by.
If we run this we get the following result (which is what we want):
Great! We have accomplished the core of this article, which was to dynamically sort our objects based on the parameters.
Now, when you actually call your sort method, you will probably need to provide some if() statements in order to change which property you are going to pass in. The beauty in this is your client is now in control of which parameters to sort by and as the business layer, you don’t need to worry about the sorting, you just provide the functionality to sort based on whatever parameter is passed in (which falls into the Open Closed Principle, your business logic is open for extension but closed for modification).

You still end up with a swtich/if statement. You really haven’t done anything to remove it. In the end you still have to do the switch/if depending on how you want to sort. You just shortened the code inside the switch/if statement.
This article was a HUGE help for me!!! Thanks!!!
You are very welcome!