Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic Sorting on List<T>

I have the following code:

   public class OMyObject
   {
       public int Id { get; set; }
       public string Value { get; set; }
       public DateTime? MyDate  { get; set; }
   }

I also have this code:

public static class ObjectExtension
{
    public static List<OMyObject> Sort<T>(this List<OMyObject> o, Func<OMyObject, T> keySort, ESortDirection direction) where T : IComparable
    {
        if (direction == ESortDirection.asc)
        {
            o.Sort((a, b) => keySort(a).CompareTo(keySort(b)));
        }
        else
        {
            o.Sort((a, b) => keySort(b).CompareTo(keySort(a)));
        }
        return o;
    }

}

Now I have a test console app which does the following:

var myObjectList = new List<OMyObject>
                               {
                                   new OMyObject {Id = 4, MyDate = DateTime.Now.AddDays(4), Value = "Test 4"},
                                   new OMyObject {Id = 2, MyDate = DateTime.Now.AddDays(2), Value = "Test 2"},
                                   new OMyObject {Id = 1, MyDate = DateTime.Now.AddDays(1), Value = "Test 1"},
                                   new OMyObject {Id = 3, MyDate = DateTime.Now.AddDays(3), Value = "Test 3"},

                               };


        Console.WriteLine("Sort By Nullable Date ASC");

        myObjectList.Sort(id => (DateTime)id.MyDate, ESortDirection.asc);

        foreach (var item in myObjectList)
        {
            Console.WriteLine(item.Id + " - " + item.MyDate + " - " + item.Value);
        }
        Console.WriteLine("Sort By ID DESC");
        myObjectList.Sort(id => id.Id, ESortDirection.desc);

        foreach (var item in myObjectList)
        {
            Console.WriteLine(item.Id + " - " + item.MyDate + " - " + item.Value);
        }

        Console.ReadLine();

So you can see that I am passing in a property to sort on.

The question is this:

How can I make my Sort() extension method generic to be able to pass in any List object to sort?

So if I created a OMySecondObject, I want to use the same method for sorting.

I tried replacing List<OMyObject> with List<T> or List<object> but that does not work.

Any thoughts?

Let me know if you need further clarification with what I am attempting to do.

Thanks

UPDATE: SOLUTION

Okay based on my discussion and answers provided (thank you very much to everyone who responded) I have figured out an easier way to do this.

I have this method which simulates a database call:

public static IEnumerable<OMyObject> GetObject()
        {
            var myObjectList = new List<OMyObject>
                                   {
                                       new OMyObject {Id = 4, MyDate = DateTime.Now.AddDays(4), Value = "Test 4"},
                                       new OMyObject {Id = 2, MyDate = DateTime.Now.AddDays(2), Value = "Test 2"},
                                       new OMyObject {Id = 1, MyDate = DateTime.Now.AddDays(1), Value = "Test 1"},
                                       new OMyObject {Id = 3, MyDate = DateTime.Now.AddDays(3), Value = "Test 3"},

                                   };
            return myObjectList;
        }

I then just sort this list as follows:

    IEnumerable<OMyObject> myObjectList = GetObject();
    myObjectList = myObjectList.OrderBy(id => id.MyDate);

Again, thank you everyone for helping me figure this out and showing me the better way of handling this.

THANKS!!

like image 600
CodeLikeBeaker Avatar asked Dec 05 '22 03:12

CodeLikeBeaker


1 Answers

You just need to define a second generic type, so you can pass in a List<T> and a separate comparison (which I called U):

public static class ObjectExtension 
{ 
    public static List<T> Sort<T,U>(this List<T> o, Func<T, U> keySort, ESortDirection direction) where U : IComparable 
    { 
        if (direction == ESortDirection.asc) 
        { 
            o.Sort((a, b) => keySort(a).CompareTo(keySort(b))); 
        } 
        else 
        { 
            o.Sort((a, b) => keySort(b).CompareTo(keySort(a))); 
        } 
        return o; 
    } 
} 

That being said, I question the usefulness of this. Why not just use the standard LINQ OrderBy?

OrderBy is slightly different, since this would do sorting in place, and OrderBy returns a new sorted IEnumerable<T>, but sticking to standards is typically more maintainable.

like image 172
Reed Copsey Avatar answered Dec 28 '22 11:12

Reed Copsey