2014-08-27 81 views
2

我有一個簡單的緩存類,用於檢索並存儲傳遞給它的任何數據。這個類唯一的操作是「Get(string key)」和「Store(string key,object data)」。我使用這個類來存儲昂貴的對象並快速檢索它們。我想要存儲數組。據我所知,IEnumerable實現本質上是懶惰實例化的。我的問題是:如果我將一個IEnumerable變量存儲到該緩存類(即LINQ查詢的結果集)中,該類將被存儲並處理其所有元素,或者每次檢索存儲的IEnumerable時,我將不得不通過所有處理暗示產生IEnumerable?我應該使用「ToList()」來觸發初始化嗎?緩存一個IEnumerable vs List進行延遲初始化

注意:我沒有訪問此緩存類的來源,我只知道它存儲和檢索對象。

+0

什麼母鹿這個簡單的緩存做的就是從字符串對象的字典不同。 – Paparazzi 2014-08-27 15:18:35

回答

3

IEnumerable是一個接口,而不是一個類。接口背後的實現定義了它的行爲。

如果在IE上需要調用ToList(),則List實現了該接口,但List> <>,而且IEnumerable爲<>。

將指針存儲爲IEnumerable <>並遍歷它與迭代列表相同。

如果IEnumerable <>是迭代器的結果,則每次訪問IEnumerable <>時都執行該實現。

實施例: 採取以下功能:使用它

public IEnumerable<int> Generator(int max) 
{ 
    for (var i = 0; i < max; i++) 
    { 
     yield return someExpensiveFunction(); 
    } 
} 

作爲

var cache = Generator(100); 

for (var i = 0; i < 2; i++) 
{ 
    foreach (var i in cache) 
    { 
     //ops 
    } 
} 

這將評估發生器(== IEnumerable的<>)的兩倍。

var cache = Generator(100).ToList(); 

for(var i = 0; i < 2; i++ 
{ 
    foreach(var i in cache) 
    { 
     //ops 
    } 
} 

這將僅評估一次發生器(== IENumerable <>)。

I.E.緩存一個IEnumerable <>是不昂貴的,如果你通過調用ToArray(),ToList()等來使其成爲'具體'。

圓頂附加指導。如果將枚舉轉換爲列表並存儲它們,則最好將存儲變量聲明爲列表。這將它的存儲模型記錄到您的用戶和/或同事。 從一個公共類的功能或屬性的結果/接口應該是收集

class X 
{ 
    private List<int> _cache; 

    public void UpdateCache(IEnumerable<int> items) 
    { 
    _cache = items.ToList(); 
    } 

    public ICollection<T> Cache 
    { 
     get{ return _cache; } 
    } 

    //even better 
    public ReadOnlyCollection<T> Items 
    { 
     get { return new ReadonlyCollection(_cache); } 
    } 
} 
+0

只是澄清,這意味着調用發電機沒有.List(),你調用發電機功能循環兩次?我的意思是,就你的例子而言,發生器函數總共會有200次迭代?如果你的外部循環爲「(var i = 0; i <4; i ++)」,總共會有400次迭代?我認爲收益率返回延遲執行,所以如果我沒有弄錯,就不會執行不必​​要的操作,然後將所有內容都存儲並在該變量中處理。 – 2014-08-28 07:35:53