带有orderby子句的linq查询的返回类型不一致

时间:2017-05-24 19:41:47

标签: c# linq

有谁知道为什么这两个查询的结果类型不同?

// 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;

我无法解释为什么q2不是 IOrderedEnumerable<int>

使用&#39;加入&#39;条款没有区别:

// 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;

2 个答案:

答案 0 :(得分:5)

在第一个查询中,没有执行实际的Select操作。 select正在选择序列中的当前项,这是一个无操作,因此简单地省略Select调用。省略Select调用后,OrderBy是查询中的最后一个调用,并返回IOrderedEnumerable<T>

对于第二个(和第三个)查询,select实际上选择了有意义的内容,并且不能省略。 (在第二个查询中,SelectMany将返回匿名类型的IEnumerable,第三个查询中的Join也是如此。)因此在这些情况下Select仍在查询中,Select会返回IEnumerable<T>

当您查看查询被翻译的内容时,这很容易,这将是以下内容的道德等同物:

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);

鉴于这些是您的查询等同的内容,应该清楚为什么只有第一个返回IOrderedEnumerable<int>

答案 1 :(得分:-3)

现在返回的实际类型(而不是声明的接口)是:

q1:OrderedEnumerable<int, int>

q2:Enumerable+WhereSelectEnumerableIterator<AnonymousType<int, int>, int>

(q3与q2相同)