2015-12-06 58 views
3

所以我知道一個典型的例子是一樣的東西如果更新包含它們的變量,LINQ查詢如何更新?

int pivot = 65; 
var socialSecurityDrawers = from person in People 
          where person.Age >= pivot 
          select person; 

pivot = 70; 
// Since we raised the retirement age, socialSecurityDrawers has been re-filtered accordingly 

但我在查詢from person in People where person.Age >= pivot select person變量pivot如何更新困惑。據我所知,該查詢是由編譯器認爲是

var socialSecurityDrawers = People.Where(p => p.Age > pivot); 

然而,由於樞軸是一個int並且因此類型,我不知道如何傳入pivot成λ表達式基本上使得它對pivot的引用,除非有一些繼續的拳擊。那會發生什麼?如果沒有,那麼這有點讓我想起了JavaScript中的hoisting,我想知道這是否是一個很好的比喻。

+1

它被稱爲閉包,並且涉及到一些編譯器魔法。基本上,編譯器會創建一個類來包裝該「int」值,並將該類的引用傳遞給Where方法,並將方法的出現值替換爲指向該類中的字段的方法。這就是爲什麼如果你稍後改變它,它也會在閉包中更新。 – MarcinJuraszek

+0

提示:想象一下,你有一個類(引用類型)實例和'int pivot'字段。 –

+0

以下文章應回答您的問題:http://stackoverflow.com/questions/852747/does-c-sharp-pass-by-value-to-lambdas –

回答

3

讓我們看看會發生什麼。 The compiler generates下面的顯示類:

[CompilerGenerated] 
private sealed class <>c__DisplayClass0_0 
{ 
    public int pivot; 
    internal bool <M>b__0(Person person) 
    { 
     return person.Age >= this.pivot; 
    } 
} 

並打開你的方法爲:

C.<>c__DisplayClass0_0 <>c__DisplayClass0_ = new C.<>c__DisplayClass0_0(); 
IEnumerable<Person> arg_1F_0 = new List<Person>(); 
<>c__DisplayClass0_.pivot = 65; 
arg_1F_0.Where(new Func<Person, bool>(<>c__DisplayClass0_.<M>b__0)); 
<>c__DisplayClass0_.pivot = 70; 

因此,它實際上更新顯示類裏面的價值。當構造Enumerable.Where時,它將傳遞駐留在同一顯示類中的委託,確保在決定執行查詢後更新該值。