官網上給的案例:
// Custom class. class Clump<T> : List<T> { // Custom implementation of Where(). public IEnumerable<T> Where(Func<T, bool> predicate) { Console.WriteLine("In Clump's implementation of Where()."); return Enumerable.Where(this, predicate); } } static void AsEnumerableEx1() { // Create a new Clump<T> object. Clump<string> fruitClump = new Clump<string> { "apple", "passionfruit", "banana", "mango", "orange", "blueberry", "grape", "strawberry" }; // First call to Where(): // Call Clump's Where() method with a predicate. IEnumerable<string> query1 = fruitClump.Where(fruit => fruit.Contains("o")); Console.WriteLine("query1 has been created.\n"); // Second call to Where(): // First call AsEnumerable() to hide Clump's Where() method and thereby // force System.Linq.Enumerable's Where() method to be called. IEnumerable<string> query2 = fruitClump.AsEnumerable().Where(fruit => fruit.Contains("o")); // Display the output. Console.WriteLine("query2 has been created."); } // This code produces the following output: // // In Clump's implementation of Where(). // query1 has been created. // // query2 has been created.
這樣看好像並沒有多少用處。
.AsEnumerable()是延遲執行的,實際上什么都沒有發生,當真正使用對象的時候(例如調用:First, Single, ToList....的時候)才執行。
下面就是.AsEnumerable()與相對應的.AsQueryable()的區別(我從其他地方找到的):
AsEnumerable將一個序列向上轉換為一個IEnumerable, 強制將Enumerable類下面的查詢操作符綁定到后續的子查詢當中。
AsQueryable將一個序列向下轉換為一個IQueryable, 它生成了一個本地查詢的IQueryable包裝。
- .AsEnumerable()延遲執行,不會立即執行。當你調用.AsEnumerable()的時候,實際上什么都沒有發生。
- .ToList()立即執行
- 當你需要操作結果的時候,用.ToList(),否則,如果僅僅是用來查詢不需要進一步使用結果集,並可以延遲執行,就用.AsEnumerable()/IEnumerable /IQueryable
- .AsEnumerable()雖然延遲執行,但還是訪問數據庫,而.ToList()直接取得結果放在內存中。比如我們需要顯示兩個部門的員工時,部門可以先取出放置在List中,然后再依次取出各個部門的員工,這時訪問的效率要高一些,因為不需要每次都訪問數據庫去取出部門。
- IQueryable實現了IEnumberable接口。但IEnumerable<T> 換成IQueryable<T>后速度提高很多。原因:
- IQueryable接口與IEnumberable接口的區別: IEnumerable<T> 泛型類在調用自己的SKip 和 Take 等擴展方法之前數據就已經加載在本地內存里了,而IQueryable<T> 是將Skip ,take 這些方法表達式翻譯成T-SQL語句之后再向SQL服務器發送命令,它並不是把所有數據都加載到內存里來才進行條件過濾。
- IEnumerable跑的是Linq to Object,強制從數據庫中讀取所有數據到內存先。
