Почему расширение Linq OrderBy не влияет на список, в котором оно вызывается?

Я пытаюсь написать общий метод расширения сортировки для списка на основе имени столбца строки и linq.

У меня здесь большая часть, но она пока не работает. Логика взята из этот сайт.

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;
}

шагая через этот код, я вижу, что список отсортирован правильно, но при возврате он не влияет на список, который я передал. Я предполагаю, что AsQueryable или OrderBy создает новый объект в памяти, и я больше не указываю на та же ссылка. У кого-нибудь есть советы о том, как сделать эту работу подходящей или запретить это, другое решение? Спасибо!

3 ответов


Это другой список. The ToList() вызов создает новый List<T> экземпляр, полностью отдельный от List<T> Это было передано в метод. В нем будут те же элементы, возможно, в другом порядке, но сам список-это другой объект.

кстати, dynamic linq уже делает это, поэтому вы можете проверить это. Вы можете начать читать об этом здесь.


есть ли у кого-нибудь советы о том, как сделать эту работу подходящей или запретить это, другое решение?

Если вы хотите изменить исходный список, используйте List<T>.Sort.


одна из основных идей LINQ заключается в том, что он не изменяет вещи, которые он призвал.

OrderBy() можно вызвать на любой IEnumerable<T>, даже те, которые не подкреплены ничем, напоминающим список (например, он генерируется на лету). И было бы действительно непоследовательно, если бы он сделал что-то вроде: "Если источник IList<T>, сортирует его и возвращает исходную ссылку. Если это не так, создает новую отсортированную последовательность."