tags:

views:

244

answers:

2

Hi Folks,

I have the following class defined in C#

class myClass<T,U>
{
    public T PropertyOne { get; set; }
    public U PropertyTwo { get; set; }
}

I need to write a function that reorder a list of myClass objects and takes two other parameters which define how I do this reorder: does my reordering depend on PropertyOne or PropertyTwo and is it ascending or descending. Let's say this two parameters are boolean. With my current knowledge in LINQ, I would write:

public IList<myClass<T,U>> ReOrder(IList<myClass<T,U>> myList, bool usePropertyOne, bool ascending)
{
    if (usePropertyOne)
    {
        if (ascending)
        {
            return myList.OrderBy(o => o.PropertyOne).ToList();
        }
        else
        {
            return myList.OrderByDescending(o => o.PropertyOne).ToList();
        }
    }
    else
    {
        if (ascending)
        {
            return myList.OrderBy(o => o.PropertyTwo).ToList();
        }
        else
        {
            return myList.OrderByDescending(o => o.PropertyTwo).ToList();
        }
    }
}

What could be a more efficient/elegant way to do that ? How can I declare the Func,TResult> keySelector object to reuse when I call either OrderBy or OrderByDescending? I'm interesting in the answer since in my real life, I can have more than two properties.

+1  A: 
public IList<myClass<T,U>> ReOrder(IList<myClass<T,U>> myList, Func<myClass<T,U>, object> selector, bool ascending)
{
  if (ascending)
  {
    return myList.OrderBy(selector).ToList();
  }
  else
  {
    return myList.OrderByDescending(selector).ToList();
  }
}
Femaref
+1  A: 
public IList<T> ReOrder<T, U>(
  IList<T> myList,
  Func<T, U> keySelector,
  bool ascending) 
{ 
  Func<IEnumerable<T>, IEnumerable<T>> orderingFunc =
    ascending ?
    x => x.OrderBy(keySelector) :
    x => x.OrderByDescending(keySelector);

  return orderingFunc(myList).ToList();
}

If you wanted to restrict this to MyClass only, you could use the following signature:

public IList<T> ReOrder<T, U, V>(
  IList<myClass<T, U>> myList,
  Func<myClass<T, U>, V> keySelector,
  bool ascending) 

If your issue is that you have a bool and want a keySelector, but can't have a keySelector variable because it would have to possibly return both T and U types, then see this answer: http://stackoverflow.com/questions/966344/generic-linq-ordering-function

David B
with your answer and the link I have got all the information I was looking for. Thanks a lot!
PierrOz