2012-09-20 69 views
3

我正在設計一個有幾個函數返回對象列表的類。我注意到當我的IEnumerable<T>轉換爲List<T>時調試變得更容易,因爲可以在監視窗口中查看對象。但是,我不確定這是否是IEnumerable的最佳做法。返回IEnumerable <T>或立即轉換爲列表<T>?

問:哪個更好?

public IEnumerable<MyData> GetData() 
{ 
    return Foo(); 
} 

public IEnumerable<MyData> GetData() 
{ 
    return Foo().ToList(); 
} 

回答

5

良好做法 - 除非有充分的理由/要求,否則不要做工作。所以除非你有特殊的理由 - 只需返回IEnumerable<MyData>而不用調用ToList()/ ToArray()就可以了。

可能的原因是:

  • 功能有望完成可能延遲枚舉
  • 你期望的結果被列舉的評價多次
+0

兩個(好的)理由的一個小例子對理解非常有幫助。 – martinstoeckli

2

更好的回報IEnumerable<..>隨着越來越多的泛型類型。在之後,主叫方可以決定如何處理它。在情況下返回在兩種情況下IEnumerable<..>,所以沒有任何理由運行ToLIst(),只是返回IEnumerable

+2

+0:良好的建議...對於另一個問題:)請注意,返回類型是相同的兩個樣本... –

+0

@AlexeiLevenkov:將重新回答,以適應問題 – Tigran

+0

+1編輯,也I認爲「沒有任何理由」是太強大了(我的答案中有一對)。 –

1

這真的取決於你的需求。方法簽名的返回類型也是該方法合同的一部分。返回IEnumerable的方法表示一個值流,而返回List(或更抽象的Collection)的方法返回可變的值集合。

我通常會試着跟上以下做法。在當存在關於值的數量或其中加載所有值將花費相當長的時間/資源(例如查詢結果)沒有固定知識使用一個IEnumerable或的IObservable

  • 嘗試和流數據。
  • 將數組用於預先已知的不應該可變的固定集合。
  • 對於可以突變的預先已知的固定集合使用ICollection。
+0

在這種情況下,該類建立數據庫連接並讓您從數據庫中檢索數據列表。我仍然懷疑:) – l33t

+0

我增加了一些最佳做法。在你的情況下,我會去IEnumerable,因爲從數據庫檢索數據將需要一些時間,它不太可能的數量,如果數據是事先知道的 – Polity

1

如果您使用的是要處理的工作單元,我最好使用元素列表,因爲一旦處置完畢,您將無法獲取元素。

在所有其他情況下,它可以返回通用的IEnumerable,因爲它提供了更好的靈活性。

最後,這一切都歸結爲您的要求,請注意,IEnumnerable不會在分配給變量的確切時刻檢索元素,而是在枚舉時檢索元素。

+0

在這種情況下,數據從數據庫(單身人士)檢索本身是永遠不會處置。 – l33t

+0

當然,當您使用實體框架或其他ORM並且實現工作模式單元時,我會引用這些案例。 – Freeman

+0

+1非常重要的一點。在正常情況下,返回不要調用ToList。但是當在外部作用域中使用可能會改變的東西(連接,關閉)時,您必須首先使用ToList。 – Sruly

0

返回的IEnumerable讓來電者決定如何處理做結果 - 要麼枚舉它,要麼將其傳遞給其他目錄,而不在當前時刻枚舉它。 ToList()強制將數據枚舉到此處,然後傳遞給調用者。

因此-IEnumerable最有可能是兩者中較好的一個 - 但是在調試時使用ToList會更容易。

+2

框架設計指南建議用最具體的類型來定義合約,而不是'IEnumerable'數組。由於FGD是內部類型,所以不要返回'List '。 Aray應該在您複製時返回,'Collection '當您保留對該集合的引用時(所以不得複製)。當然,這個準則是針對可重用的框架的,而不是針對LOB應用程序的。 – Steven

1

IEnumerable<T>是提供呼叫者T的集合的合同。然而,當您使用IList<T>List<T>,你所提出的建議,他們可以直接添加或刪除元素(不通過任何方法,如添加或註冊你可以去有你的班級實施)。如果您的意圖僅僅是讓調用者看到'項目',IEnumerable是更好的合同。

雖然它不是100%,但我將IEnumerable返回值視爲只讀集合。

易於調試應該是次要的好設計。我建議你簡單地單元測試你的類,而不是依賴於能夠在運行時偷看內部。但是,在大多數情況下,調試器將「基本」類顯示爲第一項。所以IEnumerable的第一個項目是你實際使用的List。它只需要再一次'擴大'就可以看到成員!

0

有一個簡單的規則:返回更多concrette,接受更通用的。

如果您的返回值確實是IEnumerable<>,則按原樣返回。但從來沒有這樣做:

public IEnumerable<MyData> GetData() 
{ 
    return this.list; // list = new List<MyData>(); 
} 

代碼超過限制呼叫者沒有任何需要。它將成爲一個列表,並且調用者無論如何都能夠將其列出並清除它。

相關問題