arserbin3
arserbin3

Reputation: 6158

Does LINQ to Objects keep its order

I have a List<Person> and instead want to convert them for simple processing to a List<string>, doing the following:

List<Person> persons = GetPersonsBySeatOrder();
List<string> seatNames = persons.Select(x => x.Name).ToList();

Console.WriteLine("First in line: {0}", seatNames[0]);

Is the .Select() statement on a LINQ to Objects object guaranteed to not change the order of the list members? Assuming no explicit distinct/grouping/ordering is added

Also, if an arbitrary .Where() clause is used first, is it still guaranteed to keep the relative order, or does it sometimes use non-iterative filtering?


As Fermin commented above, this is essentially a duplicate question. I failed on selecting the correct keywords to search stackoverflow

Preserving order with LINQ

Upvotes: 19

Views: 2696

Answers (3)

Joshua
Joshua

Reputation: 43317

Yes, Linq Select is guaranteed to return all its results in the order of the enumeration it is passed. Like most Linq functions, it is fully specified what it does. Barring handling of errors, this might as well be the code for Select:

IEnumerable<Y> Select<X, Y>(this IEnumerable<X> input, Func<X, Y> transform)
{
    foreach (var x in input)
        yield return transform(x);
}

But as Samantha Branham pointed out, the underlying collection might not have an intrinsic order. I've seen hashtables that rearrange themselves on read.

Upvotes: 1

Samantha Branham
Samantha Branham

Reputation: 7451

It depends on the underlying collection type more than anything. You could get inconsistent ordering from a HashSet, but a List is safe. Even if the ordering you want is provided implicitly, it's better to define an explicit ordering if you need it though. It looks like you're doing that judging by the method names.

Upvotes: 2

Andrew
Andrew

Reputation: 551

In current .Net implementation it use such code. But there are no guarantee that this implementation will be in future.

private static IEnumerable<TResult> SelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
{
  int index = -1;
  foreach (TSource source1 in source)
  {
    checked { ++index; }
    yield return selector(source1, index);
  }
}

Upvotes: 1

Related Questions