2011-03-31 39 views
0

我正準備構建我自己的IEnumerable類,它在第一次迭代它時對所有項目執行一些操作,然後我開始想,框架已經有我可以使用的東西了?內置.Net IEnumerable類延遲執行?

這裏就是我是建設讓你有一個想法是什麼我在尋找:

public class DelayedExecutionIEnumerable<T> : IEnumerable<T> 
{ 
    IEnumerable<T> Items; 
    Action<T> Action; 
    bool ActionPerformed; 

    public DelayedExecutionIEnumerable(IEnumerable<T> items, Action<T> action) 
    { 
     this.Items = items; 
     this.Action = action; 
    } 

    void DoAction() 
    { 
     if (!ActionPerformed) 
     { 
      foreach (var i in Items) 
      { 
       Action(i); 
      } 
      ActionPerformed = true; 
     } 
    } 

    #region IEnumerable<IEntity> Members 

    public IEnumerator<T> GetEnumerator() 
    { 
     DoAction(); 
     return Items.GetEnumerator(); 
    } 

    #endregion 

    #region IEnumerable Members 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     DoAction(); 
     return Items.GetEnumerator(); 
    } 

    #endregion 
} 
+0

什麼會這樣做的目的是什麼? – FreeAsInBeer 2011-03-31 04:03:08

+1

我不知道框架中內置的任何東西,並且您的實現似乎按照您的要求進行。我會提到的唯一情況是,如果多個線程同時調用GetEnumerator(),那麼您的代碼可能會很容易出現問題。 – dlev 2011-03-31 04:06:02

+3

爲什麼你想循環,並在返回之前執行你所有的動作?迭代時,您可以更輕鬆地執行每個項目的動作和「yield return」,因此只需要一次迭代並進一步延遲執行動作。 – 2011-03-31 04:21:03

回答

2

Iteratorsyield讓您可以輕鬆創建自己的懶惰枚舉序列。

在你的情況,你可以很容易濫用選擇LINQ的方法。

items.Select(i=>{DoStuff(i); return i;}); 

也許包裝它?

public static IEnumerable<T> DoStuff<T>(this IEnumerable<T> items, Action<T> doStuff) 
{ 
    return items.Select(i=>{doStuff(i); return i;}); 
} 

(手寫未測試的代碼,請謹慎使用)

2

我不知道有,它正是你正在嘗試做的事情,但我會建議您可以使用懶人<牛逼>這一點,很會照顧的線程安全性問題(每個單項的):

public class DelayedExecutionIEnumerable<T> : IEnumerable<T> 
{ 
    List<Lazy<T>> LazyItems; 

    public DelayedExecutionIEnumerable(IEnumerable<T> items, Action<T> action) 
    { 
     // Wrap items into our List of Lazy items, the action predicate 
     // will be executed only once on each item the first time it is iterated. 
     this.LazyItems = items.Select(
      item => new Lazy<T>(
       () => 
        { 
         action(item); 
         return item; 
        }, 
        true)).ToList(); // isThreadSafe = true 
    } 

    #region IEnumerable<IEntity> Members 

    public IEnumerator<T> GetEnumerator() 
    { 
     return this.LazyItems.Select(i => i.Value).GetEnumerator(); 
    } 

    #endregion 


    #region IEnumerable Members 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return this.LazyItems.Select(i => i.Value).GetEnumerator(); 
    } 

    #endregion 
}