Why does the Linq OrderBy extension not affect the list it is called on?

12,755

Solution 1

It's a different list. The ToList() call creates a new List<T> instance, entirely separate from the List<T> that was passed into the method. It will have the same items in it, probably in a different order, but the list itself is a different object.

By the way, dynamic linq already does this so you might want to check it out. You can start reading about it here.

Solution 2

Does anyone have some tips on how to make this work appropriately, or barring that, another solution?

If you want to modify the original list, use List<T>.Sort.

Solution 3

One of the basic ideas behind LINQ is that it does not modify the things its called on.

OrderBy() can be called on any IEnumerable<T>, even those that aren't backed by anything resembling a list (e.g. it's generated on the fly). And it would be really inconsistent if it did something like: “If the source is IList<T>, sorts it and returns the original reference. If it doesn't, creates a new sorted sequence.”

Share:
12,755

Related videos on Youtube

IronicMuffin
Author by

IronicMuffin

C#/TSQL developer at a mid-sized corporation.

Updated on June 04, 2022

Comments

  • IronicMuffin
    IronicMuffin almost 2 years

    I am attempting to write a generic sort extension method to List based on a string column name and linq.

    I have most of it here, but it doesn't work just yet. The logic is taken from this site.

    public static List<T> Sort<T>(this List<T> list, string sortColumn, string sortOrder) 
    {
        if (string.IsNullOrWhiteSpace(sortColumn))
            return list;
    
        int order = sortOrder == "desc" ? -1 : 1;
    
        var param = Expression.Parameter(typeof(T), "x");
        var sortExpression = Expression.Lambda<Func<T, object>>(Expression.Property(param, sortColumn), param);
        list = list.AsQueryable().OrderBy(sortExpression).ToList();
    
        return list;
    }
    

    Stepping through this code I see that list is sorted properly, but when returned, it has no effect on the list I passed in. I'm guessing AsQueryable or OrderBy is creating a new object in memory and I'm no longer pointing to the same reference. Does anyone have some tips on how to make this work appropriately, or barring that, another solution? Thanks!

    • ChrisF
      ChrisF almost 13 years
      You should just return list.AsQueryable().OrderBy(sortExpression).ToList();
  • tuutuutuut
    tuutuutuut almost 13 years
    Exactly. Which is as expected. Realistically you would want to pass in an IQueryable and return an IQueryable as well.
  • IronicMuffin
    IronicMuffin almost 13 years
    Yeah, this is essentially what I want. Thanks for the tip!