代码之家  ›  专栏  ›  技术社区  ›  mckamey

在接口中使用IEnumerator的模式

  •  3
  • mckamey  · 技术社区  · 14 年前

    IEnumerable<T> )有很多方法,所以我不能简单地 foreach .GetEnumerator() IEnumerator<T> 它的工作非常好,给我的灵活性,我需要通过一个单一的序列循环。

    . 很简单,很好用。

    但我担心这是一种反模式。他们必须知道 IEnumerator<T> .MoveNext() 调用,这样他们就可以简单地访问 .Current IEnumerator<T> 在要实现的接口中。

    1. 我没有考虑哪些陷阱?
    2. 有没有另一种模式可以让我这样做 有效率的 机制(即,我不希望创建/销毁多个副本),而不暴露 它自己?

    更新: Stream<T> IEnumerator.Current -&燃气轮机; .Peek() )然后吃掉它( IEnumerator<T>.MoveNext() -&燃气轮机; .Pop()

    我曾经 IEnumerator<T>

    内部?然后它就会被完全封装起来。我不想使用很多现有的集合,因为它们有内部存储,而我希望存储是 IEnumerable<T> iteslf公司。


    听起来大家一致认为 IEnumerator<T> ValueType 以及不知道世界的先验状态 IEnumerator<T> 一般来说,把它传出去是个坏主意。

    我听过的最好的建议是创建我自己的类,然后传递给别人。还有其他建议吗?

    4 回复  |  直到 14 年前
        1
  •  1
  •   Dan Bryant    14 年前

    IEnumerator<T> . 正如您所提到的,这里肯定存在一些紧密耦合,因为您希望枚举器在每个方法的入口处处于特定的状态。听起来您真正想要的是类似Stream类的东西,它既是一个集合(排序)又是一个迭代器(具有当前位置的概念)。我会将您的迭代和您需要的任何其他状态包装到您自己的类中,并将各种方法作为该类的成员

        2
  •  6
  •   Jon Skeet    14 年前

    你应该 IEnumerator<T> 周围。除此之外,它可能有一些 非常

    using System;
    using System.Collections.Generic;
    
    class Test
    {
        static void ShowCurrentAndNext(IEnumerator<int> iterator)        
        {
            Console.WriteLine("ShowCurrentAndNext");
            Console.WriteLine(iterator.Current);
            iterator.MoveNext(); // Let's assume it returns true
            Console.WriteLine(iterator.Current);
        }
    
        static void Main()
        {
            List<int> list = new List<int> { 1, 2, 3, 4, 5 };
            using (var iterator = list.GetEnumerator())
            {
                iterator.MoveNext(); // Get things going
                ShowCurrentAndNext(iterator);
                ShowCurrentAndNext(iterator);
                ShowCurrentAndNext(iterator);
            }
        }
    }
    

    要尝试的几个更改:

    using (List<int>.Enumerator iterator = list.GetEnumerator())
    

    using (IEnumerator<int> iterator = list.GetEnumerator())
    

    尝试预测每种情况下的结果:)

    现在承认这是一个特别邪恶的例子,但它确实展示了一些与传递可变状态相关的角落案例。我强烈建议您在“中心”方法中执行所有迭代,该方法仅使用当前值调用适当的其他方法。

        3
  •  2
  •   Adam Robinson    14 年前

    我强烈建议不要把普查员自己传来传去;除了需要当前值之外,您还有什么理由这样做?

    foreach 处理实际枚举的循环。

        4
  •  2
  •   Drew Noakes    14 年前

    您可能还想看看被动框架。