2

I'm trying to sort a List<T>, without using OrderBy, OrderByDescending, where T is a custom class. Code:

class Something
{
    public string Category { get; set; }
    public int Fingers { get; set; }
    public DateTime Creation { get; set; }
}

The list order it's based on any property of T.

class BigRoom
{
    var Room = new Room(new List<Something>());
}

class Room<T> where T: class, new()
{
    List<T> baseList;

    public Room(List<T> listPar)
    {
        baseList = listPar;

        var prop = /* get any property from T with reflection... */

        // How to set a comparer here, if we know prop (type, value...)
        baseList.Sort(...);

        // go do something with reordered list
    }
}

I can do it knowing T and its properties, using lambda expressions or delegates.

list.Sort((x, y) => x.CompareTo(y));

But when getting prop values, it returns an object, which it doesn't implement CompareTo(), is there any way of achieving this, if so I'll be grateful.

Shin
  • 664
  • 2
  • 13
  • 30
  • 2
    Are you able to implement `IComparable` on `T`? – BanksySan Jun 19 '14 at 23:08
  • @DStanley ok well, I want to know if is possible **without** `OrderBy`, to avoid reasign `baseList` multiple times, sorting will be very constant in my project and I'd like to compare performance with `OrderBy` method... – Shin Jun 19 '14 at 23:11
  • 1
    @Tomcat AFAIK `OrderBy` uses [QuickSort](http://stackoverflow.com/questions/2792074/what-sorting-algorithm-is-used-by-linq-orderby) and I would probably go for that if you are going for performance (especially if you are getting T which you know nothing about). _sorting will be very constant in my project_ if this is the case I think you should consider some redesigns or let a DB (if one exists) do it for you – Tzah Mama Jun 19 '14 at 23:17
  • Why dont you use this: http://msdn.microsoft.com/en-us/library/vstudio/cfttsh47(v=vs.110).aspx – AK_ Jun 19 '14 at 23:30
  • @AnthonyPegram sorting will be constant by **any** property – Shin Jun 19 '14 at 23:44
  • @TzahMama no DB this time, the source is read-only for me. I've done multiple tests with OrderBy, and I'd like to implement a custom [divide_and conquer algorithm](http://en.wikipedia.org/wiki/Divide_and_conquer_algorithm), and compare them, you know, playning with... – Shin Jun 19 '14 at 23:46

3 Answers3

1

Your Room constructor can be implemented like this(note i add a random for example purposes you can have the property chosen how you like it):

using System.ComponentModel;

public Room(List<T> listPar)
{
    Random r = new Random(Environment.TickCount);
    baseList = listPar;
    var props = TypeDescriptor.GetProperties(typeof(T));
    PropertyDescriptor prop = props[r.Next(props.Count)];      

    // How to set a comparer here, if we know prop (type, value...)
     baseList.Sort((x, y) => prop.GetValue(x).ToString().CompareTo(prop.GetValue(y).ToString()));

    // go do something with reordered list
 }

So if the propertydescriptor is pointing to the Fingers property for example it will sort by those values,using the compareTo of the string class.

terrybozzio
  • 4,424
  • 1
  • 19
  • 25
0

This should get you started. You'll need to actually clean up the Compare method to handle if the values are null i.e. either weren't set or are not IComparable which is required to actually be able to do comparisons.

PropertyInfo myPropertyFromReflection = GetMyPropertySomehow();
myList.Sort(new MyComparer<TransactionRequest>(myPropertyFromReflection));


public class MyComparer<T> : IComparer<T>
{
    PropertyInfo _sortBy;
    public MyComparer(PropertyInfo sortBy)
    {
        _sortBy = sortBy;
    }

    public int Compare(T x, T y)
    {
        var xValue = _sortBy.GetValue(x) as IComparable;
        var yValue = _sortBy.GetValue(y) as IComparable;

        return xValue.CompareTo(yValue);
    }
}
TyCobb
  • 8,909
  • 1
  • 33
  • 53
-5

objectlist is a list of objects you want to sort based on Status, then by Customer Name, then by Company Name, then by Billing Address

Assume entries in the object list have the following properties:

Status, Customer Name, Company Name, Billing Address

        objectlist.Sort(delegate(Object a, Object b)
        {
            if (String.CompareOrdinal(a.Status, b.Status) == 0)
            {
                return String.CompareOrdinal(a.CustomerName, b.CustomerName) == 0 ? String.CompareOrdinal(a.CompanyName, b.CompanyName) : String.CompareOrdinal(a.BillingAddress, b.BillingAddress);
            }
            if (a.Status.Equals("Very Important!")) { return -1; }
            if (b.Status.Equals("Very Important!")) { return 1; }
            if (a.Status.Equals("Important")) { return -1; }
            if (b.Status.Equals("Important")) { return 1; }
            if (a.Status.Equals("Not Important")){ return -1; }
            return 1;
        });

Hope this helps. =)

Aaron Medacco
  • 2,903
  • 2
  • 13
  • 12
  • I don't see how this helps at all - given that the OP would have to know in advance every possible property name, type and value that could ever possibly exist for what is being sorted on... – Simon Whitehead Jun 19 '14 at 22:49