2010-06-28 66 views
9

我一直認爲返回數組比使用公共API時的列表要好,但現在似乎在列表中可以通過LINQ等獲得所有這些函數。什麼是在API中返回的最佳集合類型

爲了返回原始對象或對象的集合,這裏改變了最佳實踐嗎?

例如:

Order[] GetOrders(); 
List<Order> GetOrders(); 
IEnumerable<Order> GetOrders(); 
IQueryable<Order> Get Orders(); 
+0

請注意,以上所有類型都支持不同程度的Linq,可以通過'IEnumerable '或'IQueryable '。 – 2010-06-28 03:49:41

回答

5

我覺得最常用的類型是IEnumerable<T>

  • 有了可以使用yield關鍵字IEnumerable<T>返回類型,這使得你的方法延遲枚舉和執行。 (例如,常見的投訴是System.IO.Path.GetFiles()不返回IEnumerable<T>,但返回一個Array,這意味着當您調用該方法時,無論您是否需要,都需要枚舉所有項目。您有List<T>相同的缺點)
  • 大多數LINQ擴展方法上的IEnumerable<T>
  • IEnumerable<T>返回類型工作,不承擔具體的有關呼叫者的東西。如果調用者需要一個列表或數組,他們總是可以創建一個。
  • IEnumerable<T>List<T>Array執行,因此很容易改變您的方法的實現,並仍然支持以前的返回類型。
+0

只要確保你不允許某人將你的'IEnumerable ''投射到例如'List '並且改變它,如果這會破壞類的不變量。查看我的答案瞭解更多詳情。 – 2010-06-28 13:16:35

5

你想要集合是不可改變的嗎? IEnumerable<T> 可變嗎? IList<T>

你需要索引嗎? IList<T>

與列表或陣列,該API消費者有充分的能力來添加,刪除,刪除,清除等

隨着IEnumerable<T>,該API消費者獲得一個項目的「包」,沒有特別順序,沒有索引,也沒有方法修改集合。

在一些有限的情況下,您可能想要返回IQueryable<T>,但它們通常專用於逐個構建查詢。

一般而言,我會默認爲IEnumerable<T>。我可能會使用List<T>作爲後臺字段,但只希望允許用戶以Add()爲例 - 不要刪除,清除或其他任何內容,因此我聲明public void Add<T>(T item)只是將該項添加到後臺字段列表中。

+0

如果您不需要索引,請不要忘記ICollection 。 IList 實現ICollection ,並且只是添加索引器,IndexOf(T item),Insert(int index,T item)和RemoveAt(int index)。 – 2010-06-28 20:00:21

1

除了其他人所說的內容之外,我想補充說,除非您從某個遠程數據源檢索對象,否則不應該返回IQueryable。 IQueryable是一個查詢對象,它將代表調用者獲取結果。當使用LINQ時,IQuearyable通常會使用表達式樹來轉換以供其他系統(例如Sql Server)使用。

請參閱http://weblogs.asp.net/fredriknormen/archive/2008/12/01/returning-iqueryable-lt-t-gt.aspx瞭解更多詳情。

5

正如我通常只從屬性/方法返回不可變(不可修改)的對象,這個答案假設你想要做同樣的事情。

不要忘了ReadOnlyCollection<T>它返回一個仍然可以通過索引訪問的不可變集合。

如果您使用IEnumerable<T>和釋放你的類型到無法控制的曠野,警惕的是:

class MyClass { 
    private List<int> _list; 
    public IEnumerable<int> Numbers { 
     get { return _list; } 
    } 
} 

由於用戶可以做到這一點,並弄亂你的類的內部狀態:

var list = (List<int>)myClass.Numbers; 
list.Add(123); 

這會違反財產的只讀意圖。在這種情況下,您的吸氣器應如下所示:

public IEnumerable<int> Numbers { 
     get { return new ReadOnlyCollection<int>(_list); } 
    } 

或者,您可以撥打_list.ToReadOnly()。我全部寫出來顯示類型。這將阻止任何修改你的狀態的人(除非他們使用反射,但除非你構建像許多函數式編程語言中使用的那樣的不可變集合,這真的很難停止,而這是一個完整的其他故事)。

如果您要返回只讀集合,則最好將成員聲明爲ReadOnlyCollection<T>,因爲某些操作執行得更快(獲取計數,按索引訪問項目,複製到另一個集合)。

個人而言,我希望看到的框架包括和使用的界面是這樣的:

public interface IReadOnlyCollection<T> : IEnumerable<T> 
{ 
    T this[int index] { get; } 
    int Count { get; } 
    bool Contains(T item); 
    void CopyTo(T[] array, int arrayIndex); 
    int IndexOf(T item); 
} 

你可以使用上的IEnumerable<T>頂部擴展方法所有這些功能,但它們沒有高性能的。

相關問題