C# 键入以使用IEnumerable跟踪列表的位置

C# 键入以使用IEnumerable跟踪列表的位置,c#,C#,我正在尝试开发一个类型,用列表跟踪当前迭代位置 理想情况下,我希望使用IEnumerable接口将其与foreach循环一起使用,但该接口没有启动/停止事件,也没有钩住以重置计数的方法 目前,我已经创建了一个GetNext方法,它返回列表中的下一个值,并将计数增加1 有人知道我可以使用IEnumerable实现相同的功能,这样我就可以使用foreach循环的类型了吗 比如说,;假设一个列表包含10项。一个方法可以将该类型的实例迭代到位置4,然后方法2将从位置5到6迭代同一实例,然后方法3将从位置

我正在尝试开发一个类型,用列表跟踪当前迭代位置

理想情况下,我希望使用IEnumerable接口将其与foreach循环一起使用,但该接口没有启动/停止事件,也没有钩住以重置计数的方法

目前,我已经创建了一个GetNext方法,它返回列表中的下一个值,并将计数增加1

有人知道我可以使用IEnumerable实现相同的功能,这样我就可以使用foreach循环的类型了吗

比如说,;假设一个列表包含10项。一个方法可以将该类型的实例迭代到位置4,然后方法2将从位置5到6迭代同一实例,然后方法3将从位置7到10迭代剩余实例,因此类型实例跟踪当前位置

下面的代码非常感谢您的任何想法。谢谢

public sealed class PositionTracker<T> : IEnumerable
{
    private readonly object _syncLock = new object();
    private readonly IList<T> _list = new List<T>();
    private int _current;

    public PositionTracker(IList<T> list)
    {
        _list = list;
    }

    public T GetCurrent()
    {
        lock (_syncLock)
        {
            return _list[_current];
        }
    }

    public T GetNext()
    {
        lock (_syncLock)
        {
            T t = GetCurrent();
            if (_current < _list.Count - 1)
            {
                _current++;
            }
            return t;
        }
    } 

    public IEnumerator<T> GetEnumerator()
    {
        lock (_syncLock)
        {
            return _list.GetEnumerator();
        }
    }

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

    public void Reset()
    {
        lock (_syncLock)
        {
            _current = 0;
        }
    }

    public int Count
    {
        get
        {
            lock (_syncLock)
            {
                return _list.Count;
            }
        }
    }
}

[TestFixture]
public class PositionTrackerTests
{
    [Test]
    public void Position_CurrentPosition_Test()
    {
        List<string> list = new List<string>(new string[] { "A", "B", "C", "D" });
        PositionTracker<string> positionTracker = new PositionTracker<string>(list);

        Assert.IsTrue(positionTracker.GetNext().Equals("A"));
        Assert.IsTrue(positionTracker.GetNext().Equals("B"));
        Assert.IsTrue(positionTracker.GetNext().Equals("C"));
        Assert.IsTrue(positionTracker.GetNext().Equals("D"));
    }
}
看看收益率关键字

另外,我希望您是在C.NET 2.0+中完成此操作的。

请查看此链接:

有一个链接指向Jon Skeet的一个类。它基本上是IEnumerable的包装器,它为您提供了一个公共的SmartEnumerable.Entry类,其中包含项的索引

此外,没有什么可以阻止您这样做:

public class MyClass
{
     private List<String> list = new List<String>() { "1", "2", "3", "4", "5" }

     public IEnumerable<String> GetItems(int from, int to)
     {
          for (int i=from; i<to; i++)
               yield return list[i];
     }
}

您可以通过扩展方法和Enumerable.Select和Where的重载来实现这一点

Select和Where都有重载,其中委托被传递到项及其索引:

var input = new[]{'a','b','c','d'};
var indexed = input.Select((v,i) => new { Value = v, Index = i });
foreach (var v in indexed) {
  Console.WriteLine("Index #{0} is '{1}'", v.Index, v.Value);
}
要在第一个项目之前和最后一个项目之后触发代理,但前提是至少有一个项目:

public static IEnumerable<T> StartAndEnd<T>(this IEnumerable<T> input,
                                     Action onFirst,
                                     Action onLast) {
  var e = input.GetEnumerator();
  if (!e.MoveNext()) { yield break; }
  onFirst();
  do {
    yield return e.Current;
  } while (e.MoveNext());
  onLast();
}
结果如下:

First! Index #0 is 'a' Index #1 is 'b' Index #2 is 'c' Index #3 is 'd' Last! 代理可以通过形成在循环中检查的闭包来设置局部

更复杂的版本可以在序列的最后一个元素之前调用onLast委托,但这需要在生成该元素之前缓冲序列的一个元素以检测end

First! Index #0 is 'a' Index #1 is 'b' Index #2 is 'c' Index #3 is 'd' Last!