0

我正要构建自己的 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
}
4

2 回答 2

2

我不确定是否有某些东西可以完全满足您的要求,但我建议您为此使用 Lazy<T> ,它将解决线程安全问题(对于每个单独的项目):

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
}  
于 2011-03-31T05:30:23.137 回答
2

Iteratorsyield允许您轻松创建自己的惰性枚举数序列。

同样在您的情况下,您可以轻松滥用 LINQ 的 Select 方法。

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;});
}

(手写未测试代码,慎用)

于 2011-03-31T06:07:53.043 回答