Compteur en boucle de foreach en C#

travail de l'avant-bras: Comme je le sais,

foreach est une boucle qui itère à travers une collection ou un tableau un, à partir de 0 index jusqu'au dernier article de la collection.

Donc, si j'ai n éléments dans un tableau.

foreach (var item in arr)
{

}  

puis, Dans, la 1re itération, item=arr[0];

puis, en 2ème, item=arr[1];

.

.

.

dans la dernière (nième), item=arr[n-1];

Conclusion: de travail, il semble qu'à chaque itération, il sait que la valeur à prendre de la matrice ou elle connaît l'index de l'élément à prendre de la matrice.

maintenant ma question: Comment puis-je obtenir l'index d'un élément sans utiliser une nouvelle variable?

foreach (string item in mylist)
{
   if (item == "myitem")
   {
       // get index of item
       break;
   }
}
35
demandé sur Javed Akram 2010-12-02 20:02:48

9 réponses

cela dépend de ce que vous entendez par "ça". L'itérateur sait quel indice il est atteint, oui - dans le cas d'un List<T> ou un tableau. Mais il n'y a pas d'index général à l'intérieur de IEnumerator<T>. Qu'il s'agisse d'une itération sur une collection indexée ou non est à la hauteur de la mise en œuvre. De nombreuses collections ne prennent pas en charge l'indexation directe.

(En fait, foreach ne pas toujours utiliser un itérateur. Si le type de compilation de la collection est un tableau, le compilateur va itérer dessus en utilisant array[0],array[1] etc. De même, la collection peut avoir une méthode appelée GetEnumerator() qui renvoie un type avec les membres appropriés, mais sans aucune implémentation de IEnumerable/IEnumerator dans la vue.)

Options pour le maintien d'un indice:

  • un for boucle
  • utilisez une variable séparée
  • utilisez une projection qui projette chaque élément sur une paire d'indices/valeurs, par exemple

     foreach (var x in list.Select((value, index) => new { value, index }))
     {
         // Use x.value and x.index in here
     }
    
  • utilisez mon SmartEnumerable classe qui est un peu comme l'option précédente

toutes ces options, sauf la première, fonctionneront, que la collection soit ou non indexée naturellement.

71
répondu Jon Skeet 2010-12-02 17:14:45

Utiliser for au lieu de foreach. foreach n'expose pas son fonctionnement interne, il énumère tout ce qui est IEnumerable (qui n'a pas à avoir d'index du tout).

for (int i=0; i<arr.Length; i++)
{
    ...
}

d'Ailleurs, si ce que vous essayez de faire est de trouver l'indice d'un élément dans la liste, vous n'avez pas à parcourir par vous-même. Utilisez Array.IndexOf(item) à la place.

18
répondu Yodan Tauber 2010-12-02 17:10:29

Votre compréhension foreach est incomplète.

Il fonctionne avec n'importe quel type qui expose IEnumerable (ou implémente un GetEnumerable méthode) et utilise le IEnumerator pour itérer les éléments de la collection.

Comment Enumerator est-ce (à l'aide d'un indice, yield statement ou magic) est un détail d'implémentation.

pour réaliser ce que vous voulez, vous devez utiliser un for boucle:

for (int i = 0; i < mylist.Count; i++)
{
}

Remarque:

Obtenir le nombre d'éléments dans une liste, c'est légèrement différent selon le type de list

For Collections: Use Count   [property]
For Arrays:      Use Length  [property]
For IEnumerable: Use Count() [Linq method]
11
répondu Oded 2010-12-02 17:21:02

Ou encore plus simple, si vous ne voulez pas utiliser beaucoup de linq et pour une raison quelconque ne voulez pas utiliser une boucle for.

int i = 0;
foreach(var x in arr)
{
   //Do some stuff
   i++;
}
7
répondu BlueVoodoo 2014-08-06 12:47:03

Probablement inutile, mais...

foreach (var item in yourList.Select((Value, Index) => new { Value, Index }))
{
    Console.WriteLine("Value=" + item.Value + ", Index=" + item.Index);
}
2
répondu LukeH 2010-12-02 17:08:22

ceci n'est vrai que si vous itérez à travers un tableau; et si vous itériez à travers un autre type de collection qui n'a aucune notion d'accès par index? Dans le cas du tableau, la façon la plus facile de conserver l'indice est simplement d'utiliser une boucle vanille.

1
répondu Dan Bryant 2010-12-02 17:05:25

toutes les collections n'ont pas d'index. Par exemple, je peux utiliser un Dictionaryforeach (et parcourir toutes les clés et les valeurs), mais je ne peux pas écrire à obtenir des éléments individuels à l'aide de dictionary[0], dictionary[1] etc.

si je voulais itérer à travers un dictionnaire et garder la trace d'un index, je devrais utiliser une variable séparée que je me suis incrémenté.

0
répondu Tim Robinson 2010-12-02 17:08:12

la séquence étant itérée dans une boucle de foreach pourrait ne pas supporter l'indexation ou connaître un tel concept il a juste besoin d'implémenter une méthode appelée GetEnumerator qui retourne un objet qui au minimum a l'interface de IEnumerator bien que l'implementing il n'est pas nécessaire. Si vous savez que ce que vous itération prend en charge l'indexation et vous avez besoin de l'index, alors je suggère d'utiliser un for boucle à la place.

une classe exemple qui peut être utilisée dans foreach:

    class Foo {

        public iterator GetEnumerator() {
            return new iterator();
        }

        public class iterator {
            public Bar Current {
                get{magic}
            }

            public bool MoveNext() {
                incantation
            }
        }
    }
0
répondu Rune FS 2015-07-28 12:34:21

From MSDN:

la déclaration foreach répète un groupe des déclarations intégrées pour chaque élément dans un tableau ou un objet collection qui met en œuvre la Système.Collection.IEnumerable ou Système.Collection.Générique.IEnumerable (Of T) de l'interface.

Donc, ce n'est pas nécessairement Tableau. Ce pourrait même être une collection paresseuse sans aucune idée du nombre d'articles dans la collection.

0
répondu Manish Basantani 2015-07-28 12:35:47