192 votes

Possible d'itérer en arrière à travers un foreach?

Je sais que je pourrais utiliser pour la déclaration et obtenir le même effet, mais ce que je veux savoir, c'est, puis-je la boucle vers l'arrière par une boucle foreach en C#?

184voto

Matt Howells Points 20751

Si vous êtes sur .Net 3.5, vous pouvez faire ceci:

IEnumerable<int> enumerableThing = ...;
foreach (var x in enumerableThing.Reverse())

Il n'est pas très efficace, car il a essentiellement passer par l'agent recenseur transmet de tout mettre sur une pile apparaît à tout remettre dans l'ordre inverse.

Si vous avez un directement-indexables collection (par exemple, IList), vous devez absolument utiliser une boucle for à la place.

Si vous êtes sur .Net 2.0 et ne peut pas utiliser une boucle for (c'est à dire vous avez juste un IEnumerable), alors vous n'avez qu'à écrire votre propre fonction d'inversion, cela devrait fonctionner:

static IEnumerable<T> Reverse<T>(IEnumerable<T> input)
{
    return new Stack<T>(input);
}

Cela repose sur un comportement qui n'est peut être pas évident. Lorsque vous passez un IEnumerable de la pile constructeur qu'il va itérer dessus et poussez les éléments sur la pile. Lorsque vous parcourir par le biais de la pile, il apparaît les choses dans l'ordre inverse.

Cette et la .Net 3.5 Reverse() méthode d'extension sera bien évidemment exploser si vous la donnez un IEnumerable qui ne cesse jamais de retour des articles.

101voto

280Z28 Points 49515

Lorsque l'on travaille avec une liste (indexation directe), vous ne pouvez pas le faire de manière aussi efficace que l'utilisation d'un for boucle.

Edit: ce Qui signifie généralement, lorsque vous êtes en mesure d'utiliser un for boucle, il est probable que la méthode appropriée pour cette tâche. De Plus, pour autant qu' foreach est mis en œuvre dans l'ordre, le concept lui-même est construit pour exprimer des boucles qui sont indépendants de l'élément d'index et de l'itération de l'ordre, ce qui est particulièrement important dans la programmation parallèle. Il est de mon avis que l'itération en s'appuyant sur ordonnance ne devrait pas utiliser foreach pour le bouclage.

75voto

Jon Skeet Points 692016

Comme 280Z28 dit, pour un IList<T> vous pouvez simplement utiliser l'index. Vous pouvez le cacher dans une méthode d'extension:

public static IEnumerable<T> FastReverse<T>(this IList<T> items)
{
    for (int i = items.Count-1; i >= 0; i--)
    {
        yield return items[i];
    }
}

Ce sera plus rapide que Enumerable.Reverse() qui les tampons de toutes les données de la première. (Je ne crois pas qu' Reverse a toutes les optimisations appliquées dans la façon dont Count() .) Notez que cette mise en mémoire tampon signifie que les données sont lues complètement lors du premier démarrage de l'itération, alors qu' FastReverse va "voir" toutes les modifications apportées à la liste alors que vous parcourez. (Il sera également se briser si vous supprimez plusieurs éléments entre les itérations.)

Pour le général séquences, il n'y a aucun moyen d'itération inverse - la séquence pourrait être infinie, par exemple:

public static IEnumerable<T> GetStringsOfIncreasingSize()
{
    string ret = "";
    while (true)
    {
        yield return ret;
        ret = ret + "x";
    }
}

Que voulez-vous attendre si vous avez essayé d'effectuer une itération sur que dans le sens inverse?

7voto

RealTecWare Points 1

Si vous utilisez une Liste, vous pouvez également utiliser ce Code:

List<string> list = new List<string>();
list.Add("1");
list.Add("2");
list.Add("3");
list.Reverse();

C'est une methode que d'écrire la liste inverse est en elle-même.

Maintenant, le foreach:

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

La sortie est:

3
2
1

2voto

Josip Medved Points 2307

Pas de. ForEach juste parcourt collection pour chaque élément et de l'ordre dépend si il utilise IEnumerable ou GetEnumerator().

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X