Built in .Net IEnumerable class that defers execution?
I was about to build my own IEnumerable class that performs some action on all items the first time something iterates over it then I started wondering, does the framework already have something that I could use?
Here's what I was building so you have an idea what I'm looking for:
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
}
Iterators and yield allows you to easily create your own lazy enumerator sequence.
Also in your case, you could easily abuse Select method of LINQ.
items.Select(i=>{DoStuff(i); return i;});
Maybe wrapping it up?
public static IEnumerable<T> DoStuff<T>(this IEnumerable<T> items, Action<T> doStuff)
{
return items.Select(i=>{doStuff(i); return i;});
}
(hand-written not tested code, use with caution)
I'm not sure there is something that does exactly what you are trying to do, but I would recommend you to use Lazy<T> for this, it will take care of Thread safety issues (for each individual item):
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
}
精彩评论