C#Itreator最好的方法

时间:2009-10-23 12:54:09

标签: c# iterator

除了(IEnumerable返回GetEnumerator(),对于“foreach”IEnumerble是必不可少的)

几乎以下两种方法允许我们迭代集合。什么是

一个人的优势是什么? (我不是在问IEnumerable之间的区别 和IEnumerator)。

static void Main()
{
    IEnumerator<int> em = MyEnumerator<int>(new int[] { 1, 2, 3, 4 });
    IEnumerator<int> e = Collection<int>
                        (new int[] { 1, 2, 3, 4 }).GetEnumerator();

    while (em.MoveNext())
    {
        Console.WriteLine(em.Current);
    }

    while (e.MoveNext())
    {
        Console.WriteLine(e.Current);
    }
    Console.ReadKey(true);
}

接近1

 public static IEnumerator<T> MyEnumerator<T>(T[] vals )

 {
     T[] some = vals;

     foreach (var v in some)
     {
       yield return v;
     }
}

接近2

public static IEnumerable<T> Collection<T>(T[] vals)
     {
         T[] some = vals;

         foreach (var v in some)
         {
             yield return v;
         }
     }

2 个答案:

答案 0 :(得分:1)

如果我错了,请纠正我,但唯一的区别是IEnumerable和IEnumerator之间的区别,因为你明确表示你不是要求区别,两者都是好的......

答案 1 :(得分:1)

主要区别在于,大多数API都支持IEnumerable<T>但不支持IEnumerator<T>

您还必须记住在使用时调用Reset(),而IEnumerable<T>中的语法更明显(只需再次调用GetEnumerator)。另请参阅Eric Lipper关于重置是一个坏主意的评论;如果你的IEnumerator<T>没有实现重置,或者它是一个一次性的枚举器(在很多情况下都没用)。

另一个区别可能是您可以同时从多个线程枚举IEnumerable<T>,但IEnumerator<T>在枚举数据中存储一个位置(想象一下RandomEnumerableRangeEnumerable)。

所以结论是IEnumerable<T>更通用,但无论如何,如果你有一个函数返回一个IEnumerator<T>生成IEnumerable<T>就很简单了。

class EnumeratorWrapper<T> : IEnumerable<T>
{
    Func<IEnumerator<T>> m_generator;
    public EnumeratorWrapper(Func<IEnumerator<T>> generator)
    {
        m_generator = generator;
    }

    public IEnumerator<T> GetEnumerator()
    {
        return m_generator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return m_generator();
    }
}

使用IEnumerable<T>只是为了API一致性似乎是我的最佳解决方案。

Reset()中的IEnumerator<T>问题无论如何都会使其成为无法使用的解决方案,因此IEnumerable<T>是可行的方法。