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