我想知道为什么 GetEnumerator() 方法从 IEnumerator 中分​​离出来并放置在 IEnumerable 中。在我看来,将所有枚举器方法保留在 IEnumerator 中会更有意义。

谢谢,

斯科特

有帮助吗?

解决方案

问问自己, “想象一下,如果这是真的。”

如果所有的枚举方法是一个单一的界面上,怎么可能两个呼叫者在同一时间枚举同一个列表?

有两个接口,因为一个人说,“你可以列举了我”,而另一个人说,“这是一个跟踪给定的枚举任务的对象。”

IEnumerable接口是一个工厂,创建只要你想尽可能多的IEnumerator对象。如何以及何时这些普查员习惯,就是坚持以消费者。

其他提示

IEnumerable意味着该对象是一个集合或可以以线性方式被遍历数据的源。 IEnumerator是用于实际执行其执行迭代的接口。

由于“IEnumerable的”说:“来,我历数”(然后你说 - 怎么样,给我枚举),但是“IEnumerator的”说:“我可以枚举您的收藏!”你已经拥有了它,你就不需要得到任何更多。

您得到了很好的答案在这里。只是有些偏重。一个枚举保持状态时,它会跟踪集合中的当前对象的被列举。可通过IEnumerator.Current。而且它知道如何改变这种状态,IEnumerator.MoveNext()。保持状态,需要一个独立的对象存储状态。该状态不能被存储在集合对象内部容易因为只有一个收集对象,但可以有多于一个的枚举器。

我用“轻松”一词,因为它实际上是可能的收集跟踪它的统计员。毕竟,这是返回的迭代器集合类的GetEnumerator()方法的调用。有一个在.NET框架,这样做,Microsoft.VisualBasic.Collection一个集合类。它需要实现一个VB6合同的集合类和合同中明确规定变更集合被枚举它是合法的。这意味着当该集合被修改,它需要一些合理与所有所创建的迭代器对象。

他们想出了一个相当不错的伎俩,WeakReference的可能是受此启发。一看,看在由反射显示的代码。鼓舞人心的东西。挖掘更多一些,并在集合类找到“版本”。真棒特技。

由于经常做列举的是仅沿切向(如果有的话)相关的被列举的事情。如果IEnumerable和IEnumerator的是一样的界面,他们不能被共享,或者你需要有一定的GetEnumerator无类型的参数,允许你在对象传递给枚举。分裂他们允许枚举基础设施,以在不同类型的被潜在共享。

阅读 Bart De Smet 的帖子后 敏林克 我不再相信严格要求拆分两个接口。

例如 - 在上面的链接中,IEnumerable/IEnumerator 被折叠为单个方法接口

Func<Func<Option<T>>>

以及一些基本的实现

public static class FEnumerable
{
    public static Func<Func<Option<T>>> Empty<T>()
    {
        return () => () => new Option<T>.None();
    }

    public static Func<Func<Option<T>>> Return<T>(T value)
    {
        return () =>
        {
            int i = 0;
            return () =>
                i++ == 0
                ? (Option<T>)new Option<T>.Some(value)
                : (Option<T>)new Option<T>.None();
        };
    }

    ...

}

public static Func<Func<Option<T>>> Where<T>(this Func<Func<Option<T>>> source, Func<T, bool> filter)
{
    return source.Bind(t => filter(t) ? FEnumerable.Return(t) : FEnumerable.Empty<T>());
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top