Reputation: 9881
Does anyone know why the types of the result of these two queries is different?
// q1 is IOrderedEnumerable<int>
var q1 = from c1 in new[] { 1, 2, 3 }
orderby c1
select c1;
// q2 is IEnumerable<int>
var q2 = from c1 in new[] { 1, 2, 3 }
from c2 in new[] { 1, 2, 3 }
where c1 == c2
orderby c1
select c1;
I cannot work out why q2 is not also an IOrderedEnumerable<int>
.
Using a 'join' clause doesn't make a difference:
// q3 is IEnumerable<int>
var q3 = from c1 in new[] { 1, 2, 3 }
join c2 in new[] { 1, 2, 3 }
on c1 equals c2
orderby c1
select c1;
Upvotes: 4
Views: 110
Reputation: 203837
In the very first query there is no actual Select
operating being performed. The select
is selecting the current item in the sequence, which is a no op, so the Select
call is simply omitted. With the Select
call omitted, the OrderBy
is the last call in the query, and it returns an IOrderedEnumerable<T>
.
For the second (and third) queries, the select
is actually selecting out something meaningful, and can't be omitted. (In the second query the SelectMany
is going to return an IEnumerable
of an anonymous type, as does the Join
in the third query.) So in these cases the Select
is still there in the query, and Select
returns IEnumerable<T>
.
It's easy enough when you look at what the queries are translated to, which will be the moral equivalent of the following:
var q1a = new[] { 1, 2, 3 }.OrderBy(c1 => c1);
var q2a = new[] { 1, 2, 3 }.SelectMany(c1 => new[] { 1, 2, 3 }.Select(c2 => new { c1, c2 }))
.Where(variables => variables.c1 == variables.c2)
.OrderBy(variables => variables.c1)
.Select(variables => variables.c1);
var q3a = new[] { 1, 2, 3 }.Join(new[] { 1, 2, 3 }, c1 => c1, c2 => c2, (c1, c2) => new { c1, c2 })
.OrderBy(variables => variables.c1)
.Select(variables => variables.c1);
Given that these are what your queries are equivalent to, it should be clear why only the first one returns an IOrderedEnumerable<int>
.
Upvotes: 5
Reputation: 103535
Now the actual types returned (rather that the declared interfaces) are:
q1: OrderedEnumerable<int, int>
q2: Enumerable+WhereSelectEnumerableIterator<AnonymousType<int, int>, int>
(q3 same as q2)
Upvotes: -3