2009-10-23 34 views
0

除了(IEnumerable的返回的GetEnumerator(),为 “的foreach” IEnumerble是必不可少的)C#Itreator最好的办法

几乎以下两种方法允许我们遍历collection.What是

的优势一个在另一个? (我不问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; 
     } 
    } 

回答

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>是要走的路。

+0

超级duper解释谢谢 – udana 2009-10-23 13:15:02

+1

永远不要打电话重置。重置是一个糟糕的主意,几乎总是没有实现。如果您需要重新启动枚举,只需创建一个新的枚举器。 – 2009-10-23 16:28:06

+0

好的,所以这是反对传递IEnumerator实例的一个重点,没有重置它们是绝对不可行的。 – 2009-10-23 19:40:07

1

纠正我,如果我错了,但唯一不同的是IEnumerable和IEnumerator的之间因为你的区别专门表示你不会问这个区别,两者都是好的...