IEnumerable, IEnumerator vs foreach, quand utiliser quoi [dupliquer]

cette question a déjà une réponse ici:

  • quelqu'un peut-il m'expliquer IEnumerable et IEnumerator? 14 réponses

je passais par IEnumerable et IEnumerator , mais ne pouvait pas obtenir un point clairement..si nous avons foreach, alors pourquoi avons-nous besoin de ces deux interfaces? Être il y a tout scénario où nous devons utiliser des interfaces.Si oui, quelqu'un peut-il expliquer avec un exemple. Toutes les suggestions et remarques sont les bienvenues. Grâce.

22
demandé sur Wondering 2009-07-06 10:13:59

3 réponses

foreach utilise les interfaces dans de nombreux cas. Vous avez besoin des interfaces si vous voulez implémenter une séquence que foreach peut alors utiliser. (Les blocs itérateurs rendent généralement cette tâche de mise en œuvre très simple.)

cependant, juste occasionnellement il peut être utile d'utiliser les itérateurs directement. Un bon exemple est lorsque vous essayez de "lier" deux séquences différentes. Exemple, supposons que vous recevez deux séquences - l'une des noms, l'autre des âges, et vous voulez imprimer les deux ensemble. Vous pourriez écrire:

static void PrintNamesAndAges(IEnumerable<string> names, IEnumerable<int> ages)
{
    using (IEnumerator<int> ageIterator = ages.GetEnumerator())
    {
        foreach (string name in names)
        {
            if (!ageIterator.MoveNext())
            {
                throw new ArgumentException("Not enough ages");
            }
            Console.WriteLine("{0} is {1} years old", name, ageIterator.Current);
        }
        if (ageIterator.MoveNext())
        {
            throw new ArgumentException("Not enough names");
        }

    }
}

de Même, il peut être utile d'utiliser l'itérateur si vous souhaitez traiter (dire) le premier élément différemment pour le reste:

public T Max<T>(IEnumerable<T> items)
{
    Comparer<T> comparer = Comparer<T>.Default;

    using (IEnumerator<T> iterator = items.GetEnumerator())
    {
        if (!iterator.MoveNext())
        {
            throw new InvalidOperationException("No elements");
        }
        T currentMax = iterator.Current;

        // Now we've got an initial value, loop over the rest
        while (iterator.MoveNext())
        {
            T candidate = iterator.Current;
            if (comparer.Compare(candidate, currentMax) > 0)
            {
                currentMax = candidate;
            }
        }
        return currentMax;
    }
}

maintenant, si vous êtes intéressé par la différence entre IEnumerator<T> et IEnumerable<T> , vous pourriez vouloir penser à elle en termes de base de données: pensez à IEnumerable<T> comme table, et IEnumerator<T> comme curseur. Vous pouvez demander une table pour vous donner un nouveau curseur, et vous pouvez avoir plusieurs curseurs sur la même table en même temps.

il peut prendre un certain temps pour vraiment grok cette différence, mais juste se rappeler qu'une liste (ou un tableau, ou quoi que ce soit) n'a pas de concept de" où vous êtes dans la liste "mais un itérateur sur cette liste/tableau/quoi que ne avoir ce peu d'état est utile.

47
répondu Jon Skeet 2009-07-06 06:22:01

ce que Jon a dit.

  • IEnumerable ou IEnumerable<T> : en mettant en œuvre ceci un objet indique qu'il peut vous donner un itérateur que vous pouvez utiliser pour parcourir la séquence/collection / ensemble
  • IEnumerator ou IEnumerator<T> : si vous appelez la méthode GetEnumerator définie dans l'interface précédente, vous obtenez un objet iterator comme référence IEnumerator. Cela vous permet d'appeler MoveNext() et d'obtenir l'objet courant.
  • foreach : C# construire/façade dans un sens que vous n'avez pas besoin de savoir comment il fonctionne sous le capot. Il reçoit en interne l'itérateur et appelle les bonnes méthodes pour que vous vous concentriez sur ce que vous voulez faire avec chaque élément (le contenu de chaque bloc). La plupart du temps, vous avez juste besoin de foreach sauf si vous mettez en œuvre votre propre type ou itération personnalisée, dans ce cas, vous avez besoin d'apprendre à connaître les 2 premières interfaces.
8
répondu Gishu 2009-07-06 06:54:26

gardez à l'esprit que vous ne avez pour mettre en œuvre IEnumerator et ses variantes pour utiliser foreach - IIRC, tout ce dont il a besoin est une méthode GetEnumerator() qui retourne un objet qui a une méthode MoveNext() retournant un bool, et une propriété courante retournant un objet. Vous n'avez pas besoin D'utiliser IEnumerator et IEnumerable, bien qu'il soit généralement une très bonne idée de le faire. Voir ici pour plus d'informations.

6
répondu thecoop 2009-07-06 09:54:28