Proposition Joe
Proposition Joe

Reputation: 481

How to pass property and sortorder as parameters for sorting list in method

I have a method where I pass in a List, which is then sorted in the method.

The type ChartItemData includes properties like Average, ProportionHighScore, and ProportionLowScore. Depending on method usage, I need to sort the List inside the method on different properties, and either Ascending or Descending.

How can I specify in the parameter list of the method which property to sort on, and which sortorder to use?

I imagine I could set up an Enum for SortDirection, but I still need to find out how to pass in the property to sort on. Here is some pseudocode to illustrate what I'm after, using List.OrderBy. I could also sort the List in place with the List.Sort method, if that makes more sense.

public enum SortDirection { Ascending, Descending }

public void myMethod(List<ChartItemData> myList, "parameter propertyToSortOn", 
    SortDirection direction)
{
     if (direction == SortDirection.Ascending)
        var sorted = ChartData.OrderBy(x => x."propertyToSortOn").ToList();
     else
        var sorted = ChartData.OrderByDescending(x => x."propertyToSortOn").ToList();
}

Upvotes: 1

Views: 2246

Answers (2)

John Bustos
John Bustos

Reputation: 19574

I'd say the easiest way would be to use reflection to get the PropertyInfo from the name provided.

You can then use that PropertyInfo to get the value from each value within the list to sort the list in the following way:

public List<ChartItemData> myMethod(List<ChartItemData> myList, string propName, SortDirection direction)
{
    var desiredProperty = typeof(ChartItemData).GetProperty(propName, BindingFlags.Public | BindingFlags.Instance);

    if (direction == SortDirection.Ascending)
        return myList.OrderBy(x => desiredProperty.GetValue(x)).ToList();
    else
        return myList.OrderByDescending(x => desiredProperty.GetValue(x)).ToList();
}

Upvotes: 1

Evert
Evert

Reputation: 354

Would something like this work? It allows you to refer to the property to sort on through the second method parameter (a lambda). Otherwise you'd be pretty much stuck to reflection.

public class ChartItemData
    {
        public double Average { get; set; }
        public double HighScore { get; set; }
        public double LowScore { get; set; }

        public string Name { get; set; }
    }

    class Program
    {
        public enum SortDirection { Ascending, Descending }

        public void myMethod<T>(List<ChartItemData> myList, Func<ChartItemData, T> selector, SortDirection direction)
        {
            List<ChartItemData> sorted = null;

            if (direction == SortDirection.Ascending)
            {
                sorted = myList.OrderBy(selector).ToList();
            }
            else
            {
                sorted = myList.OrderByDescending(selector).ToList();
            }

            myList.Clear();
            myList.AddRange(sorted);
        }

        public void usage()
        {
            List<ChartItemData> items = new List<ChartItemData>();

            myMethod(items, x => x.Average, SortDirection.Ascending);
            myMethod(items, x => x.Name, SortDirection.Ascending);
        }

Upvotes: 2

Related Questions