s.Starts...">

Enumerates. Where do LINQ-to-objects keep order?

var source = new List<string> { "A1", "A2", "B1", "B2" }; var filtered = source.Where(s => s.StartsWith("A")); foreach (var s in filtered) Console.WriteLine(s); // outputs first A1 and then A2 

Enumerable.Where seems to preserve the original order of elements when used in ordered IEnumerable (e.g. List<T> or T[] ). It's always like that? If so, where is this documented?

+7
source share
10 answers

Microsoft is indeed documenting that LINQ to Objects keeps order. The document http://msdn.microsoft.com/en-us/library/dd460677%28v=vs.110%29.aspx says

At PLINQ, the goal is to maximize performance while maintaining correctness. The query should be executed as quickly as possible, but still produce the correct results. In some cases, correctness requires the order of the sequence of sources to be maintained; however, ordering can be computationally expensive. Therefore, by default, PLINQ does not preserve the order of the original sequence. In this regard, PLINQ resembles LINQ to SQL, but unlike LINQ to Objects, which does keep order.

As mentioned in https://stackoverflow.com/a/3607/ ... microsoft docs for some LINQ methods that do not preserve order. For example, individual documentation indicates that this method returns an unordered sequence.

+6
source

The order is preserved using the Enumerable.Where method.

A similar question was asked about SO, and the first answer breaks down which methods keep order:

Saving an order with LINQ

+6
source

This is not documented. The LINQ statement documentation is seriously lacking in many aspects, including when and when order is not maintained, when and when operation buffering is not performed, or what guarantees of complexity.

In this case, I don’t mind depending on the implementation, which preserves order, because it will do all practical implementations.

I recommend reading the Jon Skeet Edulinq series, where before introducing functionality, he explains what you need and what you should not expect from the operator.

+1
source

Enumerable.Where keep the order of IEnumerable<T> . This is not documented, therefore it is not a guarantee, however, the implementation is performed sequentially through IEnumerable<T> sequentially - in essence, preserving the order - although this order depends on the base order of IEnumerable<T> . (For example, if the HashSet<T> not ordered, but because the enumerated HashSet<T> unordered.)

However, it includes special implementations for processing certain types (such as arrays and List<T> ), so it is possible that a certain type of collection may at some point in the future return results in a different order, if this is considered a valuable improvement from the point of view speed view / perf / etc. Documentation never specifically warrants an order.

+1
source

The Where implementation is essentially the following with some additional variable checking added to:

 public static IEnumerable<T> Where(this IEnumerable<T> source, Funct<T, bool> predicate) { foreach (T item in source) if (predicate(item)) yield return item; } 

As a result, if the output is not performed asynchronously or in parallel, it will keep order. If your source is .AsParallel, all bets are disabled in terms of order.

+1
source

LINQ decompilation where:

 private static IEnumerable<TSource> WhereIterator<TSource>(IEnumerable<TSource> source, Func<TSource, int, bool> predicate) { int num = -1; IEnumerator<TSource> getenumerator = source.GetEnumerator(); while (getenumerator.MoveNext()) { TSource current = getenumerator.Current; num++; if (predicate(current, num)) { yield return current; } } } 

Decompiling System.Collections.Generic.List.MoveNext () has the code:

 if (this.version == ts._version && this.index < ts._size) { this.current = ts._items[this.index]; this.index = this.index + 1; return true; } 

Using these two together, you can see that the order will be kept. Of course, Microsoft may change it in the future, but based on .NET 4.0, List.Where will be ordered.

+1
source

It seems like it should keep order because it is capable of running on infinite IEnumerable s.

 void Main() { foreach (var element in Count().Where (i => i%2 == 1)) { // do something with all odd numbers } } IEnumerable<int> Count() { int i = 0; while (true) yield return ++i; } 

I can't find it documented anywhere, though.

0
source

Yes, it will be ordered according to iterator. Since this is not PLINQ, the enumeration is repeated in the order of the position of the element of the enumerated type, so if you implemented some kind of custom IEnumerator for your class, it will return in that order.

0
source

Enumerable.Where follows the ordering of the items returned by the enumerator generated by calling GetEnumerator in the base collection - looking at the MSDN enumerator on List<T> documented to track indexing behavior.

0
source

Without providing an explicit OrderBy the Where method cannot guarantee the order - otherwise it would be documented as such.

0
source

All Articles