linq中的絕大多數查詢運算子都有延遲執行的特性,查詢並不是在查詢建立的時候執行,而是在遍歷的時候執行,也就是在enumerator的movenext()方法被呼叫的時候執行,大說數linq查詢操作例項方法返回的都是ienumerable,所以只有在使用foreach遍歷的時候,查詢方法才能被真正的執行.請參考c# 通過ienumberable介面和ienumerator介面實現自定義集合型別foreach功能
示例**如下:
list list=new list();輸出結果一目了然,當建立完查詢之後新增的元素也包含到了結果集中,說明查詢並沒有立即執行,而是在使用foreach遍歷之後才執行,這種特性就是linq的延遲執行.list.addrange(
newint);
ienumerable
result = list.where(n => n >= 40
);list.add(
50);
foreach (var n in
result)
不止where查詢操作符是這樣的,其他的只要返回的是ienumerable物件的都有延遲執行特性.
注:其他的一些像first、count、toarray、tolist、todictionary、tolookup這些都是立即執行的.
當然,對於linq來說,延遲執行是非常重要的,因為它把查詢的建立和查詢的執行解耦了,這讓我們可以像建立sql查詢那樣,分成多個步驟來建立我們的linq查詢。
重複執行
使用導致延遲執行的查詢操作符進行查詢操作,並且兩次或者兩次以上的使用foreach,會導致查詢重複執行,重複執行在以下兩種情況下,絕對是不好的:
1、當需要在乙個確定點儲存查詢的結果時,因為延遲執行並不會在建立查詢之後馬上得到查詢結果集,所以必須使用上面提到的toarray、tolist等方法使查詢立即執行得到結果集並進行儲存,**如下:
list list=new list();例子不是貼切,但是意思到了,此時的查詢是立即執行.list.addrange(
newint);
ienumerable
result = list.where(n => n >= 40
).tolist();
list.add(
50);
foreach (var n in
result)
2、有些查詢比較耗時,比如對乙個非常大的資料集進行操作或者通過linq遠端運算元據庫運算元據時,這個時候的重複執行會嚴重影響效能.
查詢運算子通過返回裝飾者sequence(decorator sequence)來支援延遲執行。
和傳統的集合型別如array,linked list不同,乙個裝飾者sequence並沒有自己用來存放元素的底層結構,而是包裝了我們在執行時提供的另外乙個sequence。此後當我們從裝飾者sequence中請求資料時,它就會轉而從包裝的sequence中請求資料。
比如呼叫where會建立乙個裝飾者sequence,其中儲存了輸入sequence的引用、lambda表示式還有其他提供的引數。下面的查詢對應的裝飾者sequence如圖所示:
當我們遍歷lessthanten時,實際上我們是在通過where裝飾者從array中查詢資料。
而查詢運算子鏈結建立了乙個多層的裝飾者,每個查詢運算子都會例項化乙個裝飾者來包裝前乙個sequence,比如下面的query和對應的多層裝飾者sequence:
在我們遍歷query時,我們其實是在通過乙個裝飾者鏈來查詢最初的array。
需要注意的是,如果在上面的查詢後面加上乙個轉換運算子如tolist,那麼query會被立即執行,這樣,單個list就會取代上面的整個物件模型。
Linq 延遲執行
使用linq時,其中乙個重要概念就是延遲執行,所有的謂詞求值需要等到觸發時才會被呼叫。在宣告時,它們是不執行的,除非呼叫lambda表示式,造成其中的 開始執行,否則不會被執行。如果lambda表示式執行的代價比較高 如呼叫資料庫,密集計算等 那麼為了優化 通過使用 to 方法來轉換為集合方式,減少...
Linq基礎知識小記四之操作EF
1 ef簡介 ef之於linq,ef是一種包含linq功能物件關係對映技術.ef對資料庫架構和我們查詢的型別進行更好的解耦,使用ef,我們查詢的物件不再是c 類,而是更高層的抽象 entity data model,這提供了額外的靈活性,但在效能和簡單性上面也會有所損失.ef的優點 在資料庫架構和實...
Linq之延遲載入特性
寫在前面 系列文章 延遲載入 總結上篇文章介紹了linq中常見的幾個關鍵字,並列舉了幾個例子,算是對linq如何使用有了初步了解。上篇文章中也提到了,能夠使用linq的場合有乙個要求 實現ienumerable泛型介面,或者型別相容 可以通過cast方法轉換,比如arraylist linq之lam...