程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 編寫高質量代碼改善C#程序的157個建議[IEnumerable<T>和IQueryable<T>、LINQ避免迭代、LINQ替代迭代]

編寫高質量代碼改善C#程序的157個建議[IEnumerable<T>和IQueryable<T>、LINQ避免迭代、LINQ替代迭代]

編輯:C#入門知識

本文已更新至http://www.cnblogs.com/aehyok/p/3624579.html 。本文主要學習記錄以下內容:

  建議29、區別LINQ查詢中的IEnumerable<T>和IQueryable<T>

  建議30、使用LINQ取代集合中的比較器和迭代器

  建議31、在LINQ查詢中避免不必要的迭代

  LINQ查詢方法一共提供了兩類擴展方法,在System.Linq命名空間下,有兩個靜態類:

    Enumerable類,它針對繼承了IEnumerable<T>接口的集合類進行擴展。

    Queryable類,它針對繼承了IQueryable<T>接口的集合類進行擴展。

稍加觀察我們會發現,接口IQueryable<T>實際也是繼承了IEnumerable<T>接口的,所以致使這兩個接口額方法在很大成都上是一致的。簡單的來表述就是:本地數據源用IEnumerable<T>,遠程數據源用IQueryable<T>。

  LINQ查詢從功能上來講實際上可以分為三類:LINQ to OBJECTS、LINQ to  SQL、LINQ to XML。設計Enumerable<T>和Queryable<T>兩套接口的原因是為了區別對待LINQ to OBJECTS、LINQ to SQL,兩者對於查詢的處理在內部使用的是完全不同的機制。針對LINQ to OBJECTS時,使用Enumerable中的擴展方法對本地集合進行排序和查詢等操作,查詢參數接受的是Func<>。Func<>叫做謂語表達式,相當於一個委托。針對LINQ to SQL時,則使用Queryable中的擴展方法,它接受的參數是Expression<>。Expression<>用於包裝Func<>。LINQ to SQL引擎最終會將表達式樹轉化成為相應的SQL語句,然後在數據庫中執行。

  那麼到底什麼時候使用IQueryable<T>,什麼時候使用IEnumerable<T>呢?我們來簡單的看一個例子:

     [Table(Name =  = ,Name=  Id { ;   FirstName { ;   LastName { ;   Title { ; 
            DataContext dataContext =  DataContext(ConfigurationManager.ConnectionStrings[<Employees> employees = dataContext.GetTable<Employees> temp1 = ( p  employees  p.Title.StartsWith()  p).AsEnumerable<Employees> temp2 =  p  temp1  p.FirstName.ToUpper().IndexOf() >   ( item .Format(

通過上面的代碼可以發現,雖然我們針對temp1使用的是延遲求值,但是在整個LINQ查詢語句的最後對結果使用了AsEnumerable方法,這相當於將遠程數組轉成了本地數據。通過數據庫的見識工具也可以驗證這一點。

現在來看另外一個查詢,其實還是上面的查詢只是做了簡單的修改

            DataContext dataContext =  DataContext(ConfigurationManager.ConnectionStrings[<Employees> employees = dataContext.GetTable<Employees> temp1 =  p  employees  p.Title.StartsWith()  temp2 =  p  temp1  p.FirstName.ToUpper().IndexOf() >   ( item .Format(

通過監控可以發現它是組合兩個查詢語句,而生成了一條SQL,如果不理解這一點,那麼在編寫程序時將會造成性能損耗。在LINQ to SQL的查詢中,要盡量始終使用IQueryable<T>。

在使用IQueryable<T>和IEnumerable<T>的時候還需要注意一點,IEnumerable<T>查詢的邏輯可以直接用我們自己所定義的方法,IQueryable<T>則不能使用自定義的方法,它必須先生成表達式樹,查詢由LINQ to SQL引擎處理。在使用IQueryable<T>查詢的時候,如果使用自定義的方法,則會拋出異常。

http://www.cnblogs.com/aehyok/p/3631483.html可以查看之前寫過的一篇文章中的建議10,來回顧一下比較器。

可以發現以上方式實現的排序至少存在兩個問題:

1)可擴展性太低,如果存在新的排序要求,就必須實現新的比較器。

2)對代碼的侵入性太高,為類型繼承了接口,增加了新的 方法。

那麼有沒有一種方法,即使類型只存在自動實現的屬性,也能滿足多方面的排序要求呢?答案是使用LINQ。LINQ提供了類似於SQL的語法來實現遍歷、篩選與投影集合的功能。借助於LINQ的強大功能。

 來看使用LINQ之後的代碼:

      
         
          Name { ;  
         
          BaseSalary { ;  
         
          Bouns { ;   Main(<Salary> array =  List<Salary> Salary() { Name = , BaseSalary = , Bouns =  Salary() { Name = , BaseSalary = , Bouns =  Salary() { Name = , BaseSalary = , Bouns =  Salary() { Name = , BaseSalary = , Bouns =  list= (Salary item  listBouns= (Salary item 

執行結果如下:

我們可以利用LINQ強大的功能來簡化自己的編碼,但是LINQ功能的實現本身就是借助於FCL泛型集合的比較器、迭代器、索引器的。LINQ相當於封裝了這些功能,讓我們使用起來更加的方便。在命名空間System.Linq下存在很多靜態類,這些靜態類存在的意義就是FCL的泛型集合提供擴展方法。

強烈建議你利用LINQ所帶來的便捷性,但我們仍需要掌握比較器、迭代器、索引器的原理,以便更好地理解LINQ的思想,寫出更高執行的代碼。

 無論是SQL查詢還是LINQ查詢,搜索到結果立刻返回總比搜索完所有的結果再將結果返回的效率要高。現在簡單來創建一個自定義的集合類型來說明。

       Name { ;   Age { ;   MyList : IEnumerable<Person><Person> list =  List<Person> Person(){ Name=,Age= Person(){ Name=,Age= Person(){ Name=,Age= Person(){ Name=,Age=  IteratedNum { ;  Person [ {  { .list[i] = IEnumerator<Person> ( item ++ 

簡單的進行調用

            MyList list =  temp = ( c  list  c.Age ==  =  temp2 = ( c  list  c.Age >=  

通過結果發現,第二種的性能明顯比第一種好很多。第一種查詢迭代了4次,而第二種僅有1次。

第二種查詢僅僅迭代1次是因為25正好放在list的首位,而查詢條件是大於等於20.First方法實際完成的工作就是:搜索到滿足條件的第一個元素,就從集合中返回。如果沒有符合條件的元素,它也會遍歷整個集合。

 與First方法類似的還有Take方法,Take方法接收一個整型參數,然後為我們返回該參數指定的元素個數。與First一樣,它滿足條件以後,會從當前的迭代過程直接返回,而不是等到整個迭代過程完畢再返回。如果一個集合包含了很多的元素,那麼這種查詢會為我們帶來可觀的時間效率。

再來看下面的例子,雖然LINQ查詢的最後結果都是返回包含了兩個元素"Niki"對象,但是實際上,使用Take方法僅僅為我們迭代了2次,而使用where查詢方式帶來的確實整個集合的迭代,首先修改一下集合類中的元素

        List<Person> list =  List<Person> Person(){ Name=,Age= Person(){ Name=,Age= Person(){ Name=,Age= Person(){ Name=,Age= Person(){ Name=,Age=

調用

            MyList list =  temp = ( c  list  c).Take(=  temp2 = ( c  list  c.Name ==  

結果

在實際的編碼過程中,要充分運用First和Take等方法,這樣才能為我們的應用帶來高效性,而不會讓時間浪費在一些無效的迭代中。

 

英語小貼士

1、Where can I get my baggage?——我在那裡可以取得我的行李?

2、I can'find my baggage.——我找不到我的行李。

3、Please wait for a moment while we are investigating.——我們正在調查,請稍等一下。

4、Here is my claim tag.——這是我的行李票。

5、We may have lost some baggage so we'd like to make a lost baggage report.

  Would you come with me to the office?——我們可能遺失了幾件行李,所以必須填份行李遺失報告。請和我到辦公室?

6、Could you please check it urgently?——是否可麻煩緊急查詢?

7、How soon will I find out?——多快可找到?

作者:aehyok

出處:http://www.cnblogs.com/aehyok/

感謝您的閱讀,如果您對我的博客所講述的內容有興趣,那不妨點個推薦吧,謝謝支持:-O。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved