Будет ли First () выполнять OrderBy ()? - PullRequest
8 голосов
/ 16 марта 2010

Есть ли разница в (асимптотической) производительности между

var a = Orders.OrderBy(order => order.Date).First()

и

var y = Orders.Where(order => order.Date == Orders.Min(x => x.Date)).ToList();

т.е. будет First () выполнять OrderBy ()? Я думаю, нет. MSDN говорит, что перечисление коллекции выполняется через foreach, но GetEnumerator делает это, но выражение не исключает другие расширения.

Ответы [ 4 ]

8 голосов
/ 16 марта 2010

Несколько вещей:

  • OrderBy() заказы от малого до большого, поэтому ваши две альтернативы возвращают разные элементы
  • Where() обычно ленив, поэтому ваше второе выражение вообще не выполняет никаких вычислений - только до использования.
  • В принципе, рассматриваемое поведение зависит от поставщика запросов. Например, вы можете ожидать, что поставщик запросов sql-server linq будет работать с этим иначе, чем поставщик запросов IEnumerable. Поставщик запросов может выбрать, чтобы возвращаемое значение «OrderBy» было достаточно специализированным, так что вызов First() для него распознает (либо во время компиляции, либо во время выполнения), что он выполняется на упорядоченном перечислимом и вместо сортировки, выбирает возврат (первый) минимальный элемент.
  • Специально для провайдера IEnumerable<T>, OrderBy возвращает возвращаемое перечисляемое значение, которое полностью буферизует и сортирует входные данные при каждом получении первого элемента - так, в общем базовом случае Linq-to-objects, OrderBy().First() сравнимо с OrderBy().ToArray().

Помните, что linq - это просто набор имен функций - каждый провайдер может по-своему реализовать их, поэтому вышеприведенное справедливо только для поставщика запросов System.Linq IEnumerable, но не обязательно для других.

6 голосов
/ 16 марта 2010

First вернет первую запись IEnumerable, переданную ему. Поскольку IEnumerable, переданный в First, является результатом OrderBy, ваш вопрос можно перефразировать как «Работает ли OrderBy», и, да, это так.

First не может отложить выполнение OrderBy, потому что сразу возвращает результат. Например:

        var numbers = new int[] { 9, 3, 4, 6, 7 };

        var num = numbers.First();
        Console.WriteLine(num);

        num = numbers.OrderBy(i => i).First();
        Console.WriteLine(num);

        Console.ReadLine();
6 голосов
/ 16 марта 2010

Метод First будет выполнять OrderBy (то есть, если, конечно, метод First выполняется). Когда метод First извлекает первый элемент из результата OrderBy, он должен отсортировать все элементы, чтобы выяснить, какой из них является первым.

В зависимости от того, где и как выполняется запрос (т. Е. Если механизм запросов не может оптимизировать его), второй запрос может работать довольно плохо. Если Orders.Max оценивается один раз для каждого элемента в Orders, это становится операцией O (n * n), что довольно плохо.

Существует также функциональная разница: второй запрос может возвращать более одного элемента, если есть повторяющиеся даты.

0 голосов
/ 16 марта 2010

Это не так. ЭТО БЫЛО СКАЗАНО - естественно, порядок выполнения будет исполнен в тот момент, когда кто-то попытается фактически получить первый элемент.

Но, как вы сказали, условия могут быть дополнительно определены. Таким образом, нет - он не выполняется в этот момент.

...