144

I want to order a List of objects in C# by many fields, not just by one. For example, let's suppose I have a class called X with two Attributes, A and B, and I have the following objects, in that order:

object1 => A = "a", B = "h"
object2 => A = "a", B = "c"
object3 => A = "b", B = "x"
object4 => A = "b", B = "b"

and I want to order the list by A attribute first, and when they are equals, by B element, so the order would be:

"a" "c"
"a" "h"
"b" "b"
"b" "x"

As far as I know, the OrderBy method order by one parameter.

Question: How can I order a C# List by more than one field?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Esabe
  • 1,941
  • 4
  • 16
  • 19

4 Answers4

365

Use ThenBy:

var orderedCustomers = Customer.OrderBy(c => c.LastName).ThenBy(c => c.FirstName)

See MSDN: http://msdn.microsoft.com/en-us/library/bb549422.aspx

David Neale
  • 16,498
  • 6
  • 59
  • 85
  • 2
    This did not order them for me? What am I missing?docs.OrderBy(o => o.AcctNum) .ThenBy(o => o.DocDate); – Danimal111 Nov 28 '16 at 19:07
  • You may be using an older .net. Check this answer: http://stackoverflow.com/questions/289010/c-sharp-list-sort-by-x-then-y/289040#289040. – Brad B. Dec 01 '16 at 15:32
  • 16
    For posterity: OrderBy doesn't sort the original collection, it returns an IOrderedEnumerable, so you need to assign the results of OrderBy to a variable. e.g. customers = customers.OrderBy(c=>c.Surname).ThenBy(c.Forename).ToList(); – Pseudonymous May 31 '17 at 10:59
44

Yes, you can do it by specifying the comparison method. The advantage is the sorted object don't have to be IComparable

   aListOfObjects.Sort((x, y) =>
   {
       int result = x.A.CompareTo(y.A);
       return result != 0 ? result : x.B.CompareTo(y.B);
   });
CMinus
  • 1,396
  • 1
  • 12
  • 23
8

Make your object something like

public class MyObject : IComparable
{
    public string a;
    public string b;

    virtual public int CompareTo(object obj)
    {
        if (obj is MyObject)
        {
            var compareObj = (MyObject)obj;
            if (this.a.CompareTo(compareObj.a) == 0)
            {
                // compare second value
                return this.b.CompareTo(compareObj.b);
            }
            return this.a.CompareTo(compareObj.b);
        }
        else
        {
            throw new ArgumentException("Object is not a MyObject ");
        }
    }
}

also note that the returns for CompareTo :

http://msdn.microsoft.com/en-us/library/system.icomparable.compareto.aspx

Then, if you have a List of MyObject, call .Sort() ie

var objList = new List<MyObject>();
objList.Sort();
Jason Jong
  • 4,310
  • 2
  • 25
  • 33
0

Your object should implement the IComparable interface.

With it your class becomes a new function called CompareTo(T other). Within this function you can make any comparison between the current and the other object and return an integer value about if the first is greater, smaller or equal to the second one.

Oliver
  • 43,366
  • 8
  • 94
  • 151