views:

185

answers:

2

Hello,

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!!

+10  A: 

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.

Reed Copsey
Thank you for the information, this worked like a charm. I am doing this because there are different business requirements that require the sorting of different lists based on the results of a query. Instead of requerying the database each time, I want to sort it in the business based on what the user is requesting. Some of the queries are quite large and performance of our database servers is not the best (nothing i can do about that).
Jason Heine
@Jason Heine: Huh? If you have a `List<T>` it is in memory and there is no interfacing with a database whatsoever.
Jason
@Jason, hmm, maybe I am missing something. I see what you guys are saying. Looks like what I am doing is over kill. I will do some more research on the OrderBy()
Jason Heine
@Jason Heine: If you call OrderBy on an IQueryable, it hits the database. If you call OrderBy on an IEnumerable, it sorts in memory (LINQ to SQL vs. LINQ to objects).
AaronSieb
I have taken your suggestions and figured out the better way of doing this. I have updated my question with the solution. Thank you all for helping me out!
Jason Heine
+6  A: 

There's already an OrderBy extension method.

Anton Gogolev
Exactly. take a look here http://stackoverflow.com/questions/2136145/how-to-sort-a-listt-by-double-value
Mendy