11

In C#, will using Select() to project the elements of an IOrderedEnumerable retain element order?

  • If so, how come it returns an IEnumerable, and not an IOrderedEnumerable?
  • If not, how can I achieve this (other than using foreach)?

Note that this question is NOT a duplicate of this one - I only have a Select() clause, without Distinct().

EDIT

Yes, it is LINQ to Objects. BTW, would the answer be any different if I were in fact quering some SQL DB?

bavaza
  • 10,319
  • 10
  • 64
  • 103
  • Probably. Although I don't use `select`, I often do results paging by first ordering the results and then calling `Skip` and `Take` to get the subset of those results related to the current page. The order has always reliably been maintained so I would expect it to work the same during `Select`... just test it and see – musefan Jul 15 '13 at 09:09
  • Is it LINQ to Objects? – Sergey Berezovskiy Jul 15 '13 at 09:11
  • There's a bit more detail for when to use `IOrderedEnumerable` (and it's uses, mainly applying secondary sort criteria) in this post http://stackoverflow.com/questions/8518557/when-to-return-iorderedenumerable – Adrian Thompson Phillips Jul 15 '13 at 09:13
  • http://stackoverflow.com/a/204777/477878 may be helpful – Joachim Isaksson Jul 15 '13 at 09:15
  • Select() doesn't changes order of items, but compiler can't know, whether sequence is still ordered or not. For example: `new int[]{1,3,2}.Select(x => randomInstance.Next())` – Viktor Lova Jul 15 '13 at 09:15
  • @musefan - I don't believe that to 'test and see' is good practice. This might as well have been an implementation detail, and my code would break in some future release of the .NET framework. – bavaza Jul 15 '13 at 09:31
  • @Joachim - awesome resource. Upvoting. – bavaza Jul 15 '13 at 09:32
  • @bavaza: I think your point is invalid, regardless of whether or not it is documented somewhere, it could still break in some future release if the implementation is changed. Its your responsibility to re-test if you move to a later version of something at any point in the future. – musefan Jul 15 '13 at 09:43
  • @bavaza for your edit - if you are using some LINQ provider for DB, then it's only up to provider implementation whether ordering will be preserved or not. Expression tree will be analyzed and converted into underlying query (SQL for example). EF will preserve ordering – Sergey Berezovskiy Jul 15 '13 at 09:50

1 Answers1

12

Select does not change elements order. It is a streaming operator (MSDN), which means it processes source elements in the order of source and yields projected elements one by one.

So, if you are doing projection of ordered source, projected results will retain order of source elements.


One more thing - you may be wondering why result does not implement IOrderedEnumerable<T>:

int[] items = { 2, 3, 1, 8, 5 };
IEnumerable<int> query = items.OrderBy(i => i).Select(i => i);
bool isOrdered = query is IOrderedEnumerable<int>; // false

It's because Select operator returns new iterator object (WhereSelectArrayIterator in this case) which reads items from source collection (OrderedEnumerable in this case) one by one, projects item, and returns projection. This new iterator object does not implement IOrderedEnumerable<T> interface, it's only simple IEnumerable<T>. Ordered collection is now source of iterator, but not iterator itself.

Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459