2012-07-19 58 views
1

我的印象是,我可以創建一個LINQ查詢,然後在改變參數時重用它。但似乎你不能改變源代碼集合。有人可以給我一個很好的解釋,爲什麼,因爲我明顯誤解了一些根本性的東西。LINQ查詢重用和延期執行

以下是一些示例代碼。

var source = Enumerable.Range(1, 10); 
var value = source.Where(x => x > 5); 
var first = value.ToArray(); 

source = Enumerable.Range(11, 20); 
var second = value.ToArray(); 

我期待第一次是6,7,8,9,10和第二把要了11至20

回答

6

當你這樣做:

source = Enumerable.Range(11, 20); 

您正在創建一個新的目的。但是,Where查詢仍具有對舊對象的引用。

+0

感謝jimmy和肯德爾,我會嘗試和詳細解答一下在e在LINQ下面的g產生一個由值變量引用的WhereArrayIterator。這包含對源數組和謂詞的引用。所以你可以更新源數組,這反映在結果中。但是,當我將源變量更改爲新數組時,這不會影響WhereArrayIterator中的引用。因此,WhereArrayIterator中的ref直接指向原始源數組,而不是它最初聲明的源變量。哪些是標準的東西。 – Youngs 2012-07-20 08:41:57

0
source = Enumerable.Range(11, 20); 
    var second = value.ToArray(); 

second = Enumerable.Range(11, 20); 
    var second = value.ToArray(); 

查找的差值;)

0

由於value = source.Where(x => x > 5)熱切評估的source值,但是推遲的x => x > 5部分的評價。當您重新分配來源時,原始範圍仍然存在,來源僅指向不同的範圍。簡而言之,lambda內的值是懶惰評估的。的延遲執行

source = Enumerable.Range(1,10).ToArray(); 
value = source.Where(x => x > 5); 
var first = value.ToArray(); // 6,7,8,9,10 
source.[0] = 100; 
var second = value.ToArray(); // 100,6,7,8,9,10 

實施例訪問源懶惰地(ⅰ不會推薦這種類型的代碼中的

實施例,它是如何在一個lambda訪問source變量創建一個例子的'可以推遲訪問source

source = Enumerable.Range(1,10); 
value = Enumerable.Range(1).SelectMany(n => source.Where(x => x > 5)); 
var first = value.ToArray(); 
source = Enumerable.Range(11,20); 
var second = value.ToArray(); 
+0

嗨吉米,我想我認爲源數組的行爲就好像它是lambda的一部分,因此每次都要重新評估。但顯然不是每個元素都傳遞給lambda。 – Youngs 2012-07-20 08:57:46