如何让我的InfiniteLoopingList类实现IEnumerable?

时间:2015-04-23 14:42:32

标签: c# ienumerable yield-return

我正在创建一个原型应用程序,为此我设计了一个行为类似于无限循环列表的类。也就是说,如果我的内部列表包含100个值,当我要求第101个值时,我得到第一个,第102个得到第二个,依此类推,重复。

所以我想写下面的代码:

public class InfiniteLoopingList : IEnumerable<double>
{
    double[] _values = File.ReadLines(@"c:\file.txt")
                            .Select(s => double.Parse(s, CultureInfo.InvariantCulture))
                            .ToArray();
    int _size;

    public InfiniteLoopingList()
    {
        _size = _values.Length;
    }

    public double this[int i]
    {
        get { return _values[i % _size]; }
        set { _values[i % _size] = value; }
    }

    public IEnumerator<double> GetEnumerator()
    {
        return this.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        // ???? now what ?? :(
    }
}

为此我需要实现IEnumerable,因为我理解。

这是我目前的代码:

SessionLocaleResolver

3 个答案:

答案 0 :(得分:3)

由于您实现了索引器属性,因此可以通过以下最简单的方式执行此操作:

public IEnumerator<double> GetEnumerator()
{
    int i = 0;
    while (true)
        yield return this[i++];
}

IEnumerator IEnumerable.GetEnumerator()
{
    return GetEnumerator();
}

修改
请注意,这不是无限循环。这种方法只能在i = int.MaxValue之前使用。感谢@oleksii。

答案 1 :(得分:2)

你不需要这个班......

扩展方法可以解决这个问题:

public static class InfEx
{
    public static IEnumerable<T> LoopForever<T>(this IEnumerable<T> src)
    {
        var data = new List<T>();
        foreach(var item in src)
        {
            data.Add(item);
            yield return item;
        }

        for(;;)
        {
            foreach(var item in data)
            {
                yield return item;
            }
        }
    }
}

现在你可以采用一个序列并使其成为一个循环的无限序列:

IEnumerable<Foo> mySeq = ...;
IEnumerable<Foo> infMySeq = mySeq.LoopForver();
IEnumerable<Foo> aSelectionOfInfMySeq = infMySeq.Skip(101).Take(5);

答案 2 :(得分:0)

您可以实现IEnumerator接口:

class InifniteEnumerator<T> : IEnumerator<T> {        
    private int index = -1;
    private IList<T> innerList;
    private int repeatPos;
    public InifniteEnumerator(IList<T> innerList, int repeatPos) {
        this.innerList = innerList;
        this.repeatPos = repeatPos;
    }
    public T Current {
        get {
            if (index == -1) {
                throw new InvalidOperationException();
            }
            return this.innerList[index];
        }
    }
    object IEnumerator.Current {
        get {
            return this.Current;
        }
    }
    public void Dispose() {

    }
    public bool MoveNext() {
        this.index++;
        if (this.index == repeatPos) {
            this.index = 0;
        }
        return true;
    }
    public void Reset() {
        this.index = -1;
    }
}

然后在GetEnumerator方法中返回它的一个实例:

IEnumerator IEnumerable.GetEnumerator() {
    return this.GetEnumerator();
}

public IEnumerator<T> IEnumerable<T>.GetEnumerator() {
    return new InifniteEnumerator(this, 100);
}