2009-10-23 12 views
0

Outre (IEnumerable retour GetEnumerator(), pour "foreach" IEnumerble est essentiel)C# Itreator meilleure approche

presque les deux approches suivantes nous permettent de parcourir la collection.What est

l'avantage de l'un sur l'autre? (Je ne demande pas la différence entre IEnumerable et 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); 
} 

approche 1

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

{ 
    T[] some = vals; 

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

approche 2

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

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

Répondre

1

La principale différence est que la plupart des API supportent une imputation de IEnumerable<T> mais pas de IEnumerator<T>.

Vous devez également vous rappeler d'appeler Reset() lors de son utilisation alors que la syntaxe est plus évidente dans IEnumerable<T> (Appelez à nouveau GetEnumerator). Voir aussi le commentaire d'Eric Lipper à propos de la réinitialisation étant une mauvaise idée; Si Reset n'est pas implémenté dans votre IEnumerator<T> ou est bogué, il devient un énumérateur unique (assez inutile dans beaucoup de cas).

Une autre différence peut être que vous pourriez avoir un IEnumerable<T> qui pourraient être dénombrés à partir de plusieurs threads en même temps, mais un magasin IEnumerator<T> une position dans les données énumérées (Imaginez un RandomEnumerable ou RangeEnumerable). Donc, la conclusion est que IEnumerable<T> est plus polyvalent, mais de toute façon, si vous avez une fonction retournant un IEnumerator<T> générant le IEnumerable<T> autour est simple.

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(); 
    } 
} 

Juste pour la cohérence de l'API en utilisant IEnumerable<T> semble la meilleure solution pour moi.

Mais le problème avec Reset() dans IEnumerator<T> en fait une solution inutilisable de toute façon, alors IEnumerable<T> est le chemin à parcourir.

+0

Explications de super duper Merci – udana

+1

NE JAMAIS appeler Réinitialiser. La réinitialisation était une mauvaise idée et n'est presque jamais implémentée. Si vous devez redémarrer une énumération, créez simplement un nouvel énumérateur. –

+0

Ok, donc c'est un gros point contre le fait de contourner les instances d'IEnumerator, sans réinitialiser, elles ne sont absolument pas viables. –

1

-moi si je me trompe, mais la seule différence est la différence entre IEnumerable et IEnumerator et puisque vous spécifiquement dit que vous ne demandez pas la différence, les deux sont un bon ...

Questions connexes