c# - 我实现 IEnumerator 和 IEnumerable 的类不会转到 foreach 语句

标签 c# .net foreach ienumerable ienumerator

我有一个存储字符串列表的类,我想让这个类在 foreach 语句中可用,所以我找到了这两个接口(interface)并尝试实现它们。

public class GroupCollection : IEnumerable, IEnumerator
{
    public List<string> Groups { get; set; }
    public int Count { get { return Groups.Count; } }
    int position = -1;
}

public IEnumerator GetEnumerator()
{
    return (IEnumerator)this;
}

public object Current
{
    get
    {
        try
        {
            return new Group(Groups[position]);
        }
        catch (IndexOutOfRangeException)
        {
            throw new InvalidOperationException();
        }
    }
}

public bool MoveNext()
{
    position++;
    return position < Groups.Count;
}

public void Reset()
{
    position = 0;
}

我正在遍历 GroupCollection 变量两次:

foreach (GroupCollection.Group in groups) // where groups is a GroupCollection
{
}

foreach (GroupCollection.Group in groups)
{
}

// where Group is a nested class in GroupCollection.

当它在第一个 foreach 时效果很好(此时计数为 1)。我不修改任何东西,当它进入第二个 foreach 时,它不会进入循环。我在 Debug模式下逐行检查代码,发现在第一个 foreach 之后没有调用重置。那么我应该在 foreach 之后手动调用 reset 吗?有没有更好的方法来做到这一点?

最佳答案

I don't modify anything

是的 - 您的 MoveNext() 修改类的状态。这就是为什么不应在同一个类中同时实现 IEnumerableIEnumerator 的原因。 (C# 编译器会处理迭代器 block ,但这是一种特殊情况。)您应该能够调用 GetEnumerator() 两次并获得两个完全独立的迭代器。例如:

foreach (var x in collection)
{
    foreach (var y in collection)
    {
        Console.WriteLine("{0}, {1}", x, y);
    }
}

... 应该为您提供集合中所有可能的项目对。但是,在迭代器独立时有效。

I went through the code line by line in debugging mode and found out that the reset is not called after the first foreach.

为什么你会期望它?我不相信该规范对 foreach 调用 Reset 有任何说明 - 这是一个很好的工作,因为许多实现并不真正实现它(他们抛出异常)。

基本上,您应该让您的 GetEnumerator() 方法返回一个新对象,该对象在您的数据上保持“游标”的可变状态。请注意,在 C# 中实现迭代器的最简单方法是通常使用迭代器 block (yield return 等)。

我还强烈鼓励您实现通用接口(interface),而不仅仅是非通用接口(interface);这样你的类型就可以更容易地在 LINQ 代码中使用,foreach 语句中的迭代器变量可以适本地隐式键入,等等。

关于c# - 我实现 IEnumerator 和 IEnumerable 的类不会转到 foreach 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29492712/

相关文章:

c# - WPF ListView从ListView更新源

c# - XMLDocument -> Byte[] ...如何回到 XMLDocument?

javascript - 使用 forEach() 循环数组最大数

c# - 插件模式 - IoC/DI 与否?

php - mySQL PDO 无法从表中选择

javascript - 嵌套解析 promise 之外的空数组

c# - 浏览器中的全局化、缓存控制和 HTTP 日期

c# - obj.GetType().IsInstanceOfType(typeof(MyClass)) 什么时候为真?

c# - 在修改 Cursor 的代码中重定向标准输出

c# - DISM.exe 返回代码?