Linq查询中带有orderby子句的返回类型不一致。

4

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

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

使用 'join' 子句并没有什么区别:

// 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个回答

5
在第一个查询中,实际上没有进行任何真正的 Select 操作。 Select 选择序列中的当前项,这是无用的操作,因此省略了 Select 调用。 在省略了 Select 调用后,OrderBy 是查询中的最后一个调用,并返回一个 IOrderedEnumerable<T>
对于第二个(和第三个)查询,Select 实际上在选择有意义的内容,不能省略。 (在第二个查询中,SelectMany 将返回匿名类型的 IEnumerable,第三个查询中的 Join 也是如此。) 因此,在这些情况下,查询中仍然存在 SelectSelect 返回 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>

你能说明 q2 中的 SelectMany 是如何工作的吗? - 15ee8f99-57ff-4f92-890c-b56153
很好的解释!谢谢! - Akshay Mahajan

-3

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

q1:OrderedEnumerable<int, int>

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

(q3与q2相同)


这个问题指定了变量的编译时类型,并且正确地执行了这样做。但是,您也没有回答为什么类型不同的问题。 - Servy
这并没有回答关于为什么它们不同的问题。 - Akshay Mahajan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接