2017-05-24 54 views
4

有谁知道为什么这两个查询的结果类型不同?带orderby子句的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>

使用 '加入' 条款不有所作为:

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

回答

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>

+0

你能澄清一下q2中的SelectMany吗? –

+0

好的解释!谢谢! –

-3

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

Q1:OrderedEnumerable<int, int>

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

(Q3相同Q2)

+0

问题是指定变量的*编译时间*类型,并正确执行。你也不回答为什么类型不同的问题。 – Servy

+0

这不回答关于'为什么'他们不同的问题 –