2017-05-24 86 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

這不回答關於'爲什麼'他們不同的問題 –