IEnumerable程序員
public interface IEnumerable<out T> : IEnumerable
ICollectionsql
public interface ICollection<T> : IEnumerable<T>, IEnumerable
IList函數
public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable
List性能
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable
能夠看到功能上List最強大,性能上IEnumerable更好,其實性能上都差很少,都是接口。spa
IEnumerable<T> 是linq to object。
IQueryable<T> 是linq to sql。.net
打個比方,我從Users中獲取1條數據 var q=db.Users.orderby(x=>x.id).Take(1);
對於IEnumerable<T>來講,他先會把全部數據加載到內存,而後在取一條數據。
對於IQueryable<T> 來講,他會生成一個sql語句,只是取一條數據設計
留意 .net 的類庫,會發現不多有方法返回 List<T> 或 IList<T> 的,可是不少 .net 的程序員喜歡這麼作,爲何?由於 List<T> 的功能實在太強大了吧。code
IEnumerable<T> 是延時求值的,若是在調用棧裏面輸入和輸出都是 IEnumerable<T> 的話,是最好的,由於不管調用多少次,循環都只有一次,.NET 裏面的 lambda 就是這樣的。blog
可是調用棧的輸入輸出沒法肯定的時候,狀況就比較複雜。若是你返回的是 IEnumerable<T>,有可能調用棧的上一層執行了它的迭代器,形成並不須要的屢次循環。接口
若是調用棧的上一層使用的是 List<T> 的 Copy() 方法,那麼你返回 List<T> 會比較好,若是你返回的是 IEnumerable<T>,通常是會被 ToList() 再 Copy()
因此這個問題關鍵仍是看怎麼使用返回值,來決定你編寫的函數的返回值。
使用盡量底層的、具體的類型。不要從一開始就超過你的需求來搞「抽象」。所以首先是使用 List<T>。
能返回List就不要返回IList:若是後面有方法須要IList能夠直接傳;若是後面須要用到List的屬性就能直接用
若是返回的是IList:後面有方法須要List,你得想一想我能不能轉,或者回去改;若是須要用到List的屬性,還得回去改,綜上考慮返回範圍更廣的類型好處多多。
可是,隨着你真正開始須要抽象了,你就「被迫」須要重構爲抽象的類型了。這時候再重構,要在必須的時候才進行抽象。真正會抽象的人,確定是反而不濫用抽象,是在必須的時候才抽象的。這個道理大概是「從不抽象設計」的人總也不能理解的。
有的人,很實際,你看到他的代碼就知道他的這部分程序設計已經到達那個程度、必須抽象才能用在系統中。其返回的具體數據類型「確實是」多種子類型定義的,因此才抽象。這就是把複雜的接口弄得剛剛合適的聲明程度。
而有的人,代碼的抽象老是高於實際,中間存在着含糊的、不肯定的因素,明明其輸入輸出的數據類型不具備抽象、多態處理,卻要弄一個很抽象的定義。這就是把簡單的事情弄複雜了。
假設說你設計的時候,你有多種實際子類型的考慮,你確實有多種實現代碼,那麼你就返回一個枚舉類型,明確地告訴使用者「我不能返回集合類型,我不保證明現全部的集合類型纔有的功能」。這是由於你如今要實現的東西,確實是不能用集合類型的。
反過來講,若是你輸出的東西只能用集合類型,那麼就返回集合類型,方便調用者傻瓜化地使用。未來還有其它複雜的擴展,那麼應該重構接口,增長重載新方法,而不用去修改原來使用集合類型的東西。好比說 Linq 有一系列的基於枚舉類型的功能方法,可是不是說原來基於集合類型而定義的一大堆方法就不該該設計出來。不須要放這個馬後炮。因此根據如今實際狀況,定義接口,習慣於常常在新版本中重構接口,而不是糾結在「一次性‘最完美’再也不變」的接口,就能夠了。
好比多層項目中,數據層,業務層,展示層三層中,從數據層查詢數據集到展示層須要「傳遞」2次,若是是List或者IEnumerable,會在數據層就將數據加載到內存,另外對於一個方法返回List集合,接受數據時每次都new 一個List集合 我感受是不妥的,若是數據量較大是很損性能。 而IQueryable對於數據的操做,會根據自定義的擴展方法 來生成最終的查詢語句,而不是從一開始就加載數據,這就達到了哪裏須要數據就在哪裏查詢。其實不少項目中都會有直接返回LIst的方法或者接口,這些方式不免是那些從培訓中心歷來的或者從一些書籍上看到的開發人員編寫的。
抽象都是恰到好處地抽象,才叫抽象!