Comment fonctionnent les boucles foreach en C #? [fermé]


86

Quels types de classes peuvent utiliser des foreachboucles?


5
Vous voudrez peut-être choisir une autre réponse acceptée, car celle que vous avez sélectionnée n'est pas vraiment représentative de la bonne réponse.
George Stocker

Réponses:


162

En fait, à proprement parler, tout ce dont vous avez besoin foreachest une GetEnumerator()méthode publique qui renvoie quelque chose avec une bool MoveNext()méthode et une ? Current {get;}propriété. Cependant, la signification la plus courante de ceci est "quelque chose qui implémente IEnumerable/ IEnumerable<T>, retournant un IEnumerator/ IEnumerator<T>.

Implicitement, cela inclut tout ce qui met en œuvre ICollection/ ICollection<T>, comme quelque chose comme Collection<T>, List<T>, les tableaux ( T[]), etc. Ainsi , toute « collecte de données » standard supportent en général foreach.

Pour preuve du premier point, ce qui suit fonctionne très bien:

using System;
class Foo {
    public int Current { get; private set; }
    private int step;
    public bool MoveNext() {
        if (step >= 5) return false;
        Current = step++;
        return true;
    }
}
class Bar {
    public Foo GetEnumerator() { return new Foo(); }
}
static class Program {
    static void Main() {
        Bar bar = new Bar();
        foreach (int item in bar) {
            Console.WriteLine(item);
        }
    }
}

Comment ça marche?

Une boucle foreach comme foreach(int i in obj) {...}un peu équivaut à:

var tmp = obj.GetEnumerator();
int i; // up to C# 4.0
while(tmp.MoveNext()) {
    int i; // C# 5.0
    i = tmp.Current;
    {...} // your code
}

Cependant, il existe des variantes. Par exemple, si l'énumérateur (tmp) prend en charge IDisposable, il est également utilisé (similaire à using).

Notez la différence dans le placement de la déclaration " int i" à l' intérieur (C # 5.0) par rapport à l' extérieur (jusqu'à C # 4.0) de la boucle. C'est important si vous utilisez idans une méthode anonyme / lambda dans votre bloc de code. Mais c'est une autre histoire ;-p


3
+1 pour approfondir. Normalement, je ne vais pas plus en profondeur pour une question qui peut être une question «débutante» car elle semblerait accablante pour le nouveau programmeur.
George Stocker

C'est vrai, Gortok - donc j'ai suivi avec les trucs sur les listes / tableaux / etc.
Marc Gravell

Il serait bon de mentionner la conversion implicite du runtime en variable de boucle - peut produire des exceptions d'incompatibilité de type.
Daniel Earwicker du

3
N'oubliez pas: lorsque vous utilisez un tableau avec foreach, le compilateur crée un simple for-loop(vous pouvez le voir lorsque vous travaillez avec IL).
Felix K.

1
@Marc Gravell: OK, cool! J'ai édité l'article pour le rendre plus clair - du moins pour moi. Après tout, le placement n'est pas seulement important en C # 5.0, il est toujours important, seulement qu'il a changé. J'espère que cela ne vous dérange pas.
Paul Groke

7

Depuis MSDN :

L' foreachinstruction répète un groupe d'instructions incorporées pour chaque élément d' un tableau ou d'une collection d'objets . L' foreachinstruction est utilisée pour parcourir la collection pour obtenir les informations souhaitées, mais ne doit pas être utilisée pour modifier le contenu de la collection afin d'éviter des effets secondaires imprévisibles. (c'est moi qui souligne)

Donc, si vous avez un tableau, vous pouvez utiliser l'instruction foreach pour parcourir le tableau, comme ceci:

 int[] fibarray = new int[] { 0, 1, 2, 3, 5, 8, 13 };
    foreach (int i in fibarray)
    {
        System.Console.WriteLine(i);
    }

Vous pouvez également l'utiliser pour parcourir une List<T>collection, comme ceci:

List<string> list = new List<string>();

foreach (string item in list)
{
    Console.WriteLine(item);
}

4
curieusement, selon MSDN ( msdn.microsoft.com/en-us/library/9yb8xew9(VS.80).aspx ), les types d'objets n'ont pas besoin d'implémenter IEnumerable. Tout type qui définit GetEnumerator, MoveNext, Reset et Current de la bonne manière fonctionnera. Bizarre, hein?
Sean Reilly

Soigné. Je ne savais pas ça. :-)
George Stocker


2

Voici la documentation: Article principal avec des tableaux avec des objets de collection

Il est important de noter que "Le type de l'élément de collection doit être convertible en type d'identifiant". Cela ne peut parfois pas être vérifié au moment de la compilation et peut générer une exception d'exécution si le type d'instance n'est pas attribuable au type de référence.

Cela générera une exception d'exécution s'il y a un non-Apple dans la corbeille de fruits, comme une orange.

List<Fruit> fruitBasket = new List<Fruit>() { new Apple(), new Orange() };
foreach(Apple a in fruitBasket)

Cela filtre en toute sécurité la liste uniquement pour les pommes à l'aide de Enumerable.OfType

foreach(Apple a in fruitBasket.OfType<Apple>() )

-1
IList<ListItem> illi = new List<ListItem>();
ListItem li = null;

foreach (HroCategory value in listddlsubcategory)
{
    listddlsubcategoryext = server.getObjectListByColumn(typeof(HroCategory), "Parentid", value.Id);
    li = new ListItem();
    li.Text = value.Description;
    li.Value = value.Id.ToString();
    illi.Add(li);
    IList<ListItem> newilli = new List<ListItem>();
    newilli = SubCatagoryFunction(listddlsubcategoryext, "-->");
    foreach (ListItem c in newilli)
    {
        illi.Add(c);
    }
}

-1

Des informations utiles à ce sujet sont également disponibles sur MSDN . Prenant l'essence de cet article:

Le mot clé foreach énumère une collection, en exécutant l'instruction incorporée une fois pour chaque élément de la collection:

foreach (var item in collection)
{
    Console.WriteLine(item.ToString());
}

Le compilateur traduit la boucle foreach illustrée dans l'exemple ci-dessus en quelque chose de similaire à cette construction:

IEnumerator<int> enumerator = collection.GetEnumerator();
while (enumerator.MoveNext())
{
    var item = enumerator.Current;
    Console.WriteLine(item.ToString());
}

-2

vous pouvez essayer ceci ...

List<int> numbers = new List<int>();
        numbers.Add(5);
        numbers.Add(15);
        numbers.Add(25);
        numbers.Add(35);

        Console.WriteLine("You are added total number: {0}",numbers.Count);
        foreach (int number in numbers)
        {
            Console.WriteLine("Your adding Number are: {0}", number);
        }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.