182

I know I could use a for statement and achieve the same effect, but can I loop backwards through a foreach loop in C#?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JL.
  • 78,954
  • 126
  • 311
  • 459
  • 11
    You can reverse the element (list.Reverse()) in the list before you do for each. – Akaanthan Ccoder Dec 10 '13 at 12:06
  • 1
    Also see [why-is-there-no-reverseenumerator-in-c](http://stackoverflow.com/questions/9337039/why-is-there-no-reverseenumerator-in-c) – nawfal Dec 15 '13 at 03:59
  • You would have to instantiate all the elements in the enumeration so you could reverse their order. It may not be possible. Consider the sequence: `IEnumerable Infinity() { int i = 1; while (true) yield return i++; }` How would you reverse that? – Suncat2000 Jan 30 '20 at 17:19

13 Answers13

176

If you are on .NET 3.5 you can do this:

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

It isn't very efficient as it has to basically go through the enumerator forwards putting everything on a stack then pops everything back out in reverse order.

If you have a directly-indexable collection (e.g. IList) you should definitely use a for loop instead.

If you are on .NET 2.0 and cannot use a for loop (i.e. you just have an IEnumerable) then you will just have to write your own Reverse function. This should work:

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

This relies on some behaviour which is perhaps not that obvious. When you pass in an IEnumerable to the stack constructor it will iterate through it and push the items onto the stack. When you then iterate through the stack it pops things back out in reverse order.

This and the .NET 3.5 Reverse() extension method will obviously blow up if you feed it an IEnumerable which never stops returning items.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Matt Howells
  • 40,310
  • 20
  • 83
  • 102
  • Also I forgot to mention .net v2 only please – JL. Jul 31 '09 at 09:43
  • 5
    Interesting .NET 2.0 solution. – RichardOD Jul 31 '09 at 10:29
  • 12
    Am I missing something or does your .Net 3.5 solution not actually work? Reverse() reverses the list in place and doesn't return it. Too bad, as I was hoping for a solution like that. – user12861 Mar 19 '12 at 21:00
  • 2
    Some admin mark this answer as WRONG please. Reverse() is a void[1] and so above example leads to a compile error. [1] http://msdn.microsoft.com/en-us/library/b0axc2h2(v=vs.110).aspx –  Jan 03 '14 at 05:06
  • 9
    @user12861, Micky Duncan : the answer is not wrong, you are missing something. There is a Reverse method on System.Collections.Generic.List which does an in-place reverse. In .Net 3.5 there is an extension method on IEnumerable named Reverse. I've changed the example from var to IEnumerable to make this more explicit. – Matt Howells Apr 04 '14 at 08:50
  • See [Bryan's answer to a similar question[(http://stackoverflow.com/a/3320924/199364), for an easier to follow example of the two approaches, one for Lists, the other for other IEnumerables. – ToolmakerSteve Mar 02 '17 at 20:30
  • ... Though on modern .NET, which has "yield return", [Jon Skeet's answer](http://stackoverflow.com/a/1211626/199364) is preferable for any IList, as it avoids the internal buffering that IEnumerable.Reverse has to do. – ToolmakerSteve Mar 03 '17 at 00:58
  • You can also call the extension method explicitly if you don't want to cast: `Enumerable.Reverse(myList)` – dlf Mar 14 '19 at 14:25
95

When working with a list (direct indexing), you cannot do it as efficiently as using a for loop.

Edit: Which generally means, when you are able to use a for loop, it's likely the correct method for this task. Plus, for as much as foreach is implemented in-order, the construct itself is built for expressing loops that are independent of element indexes and iteration order, which is particularly important in parallel programming. It is my opinion that iteration relying on order should not use foreach for looping.

Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
  • 6
    I find your last statement a bit too general. Surely there are cases where, for example, an IEnumerable of some kind needs to be iterated through in order? Would you not use foreach in that case? What would you use? – avl_sweden Jan 09 '17 at 15:50
  • 2
    UPDATE: See [Bryan's answer to a similar question[(http://stackoverflow.com/a/3320924/199364), for a more modern answer, using Linq, and discussing both lists, and other enumerables. – ToolmakerSteve Mar 02 '17 at 20:28
  • 2
    UPDATE: [Jon Skeet](http://stackoverflow.com/a/1211626/199364) has an even more elegant answer, that is now possible, using "`yield return`". – ToolmakerSteve Mar 03 '17 at 03:14
  • 4
    I had the same initial reaction as @avl_sweden - "iteration relying on order should not use foreach" sounds over-broad. Yes, foreach is good for expressing order-independent parallel tasks. BUT it is also an essential part of modern [iterator-based programming](https://en.wikipedia.org/wiki/Iterator). Perhaps the point is that it would be clearer/safer if there were *two distinct keywords*, to clarify whether one is *asserting* that the iterations are order-independent? [Given a language like Eiffel that can propagate contracts, such assertions could be provably true or false, for given code.] – ToolmakerSteve Mar 03 '17 at 03:32
  • 4
    The idea that foreach "is build for expressing loops that are independent of element indexes and iteration order" is incorrect. The c# language specification requires that foreach process elements in order. Either by using MoveNext on iterators or by processing indices starting at zero and incrementing by one on each iteration of arrays. – Donald Rich Jul 25 '18 at 08:52
72

As 280Z28 says, for an IList<T> you can just use the index. You could hide this in an extension method:

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

This will be faster than Enumerable.Reverse() which buffers all the data first. (I don't believe Reverse has any optimisations applied in the way that Count() does.) Note that this buffering means that the data is read completely when you first start iterating, whereas FastReverse will "see" any changes made to the list while you iterate. (It will also break if you remove multiple items between iterations.)

For general sequences, there's no way of iterating in reverse - the sequence could be infinite, for example:

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

What would you expect to happen if you tried to iterate over that in reverse?

Rob
  • 25,984
  • 32
  • 109
  • 155
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Just curiosity, why use ">= 0" instead of "> -1"? – Chris S Jul 31 '09 at 09:50
  • 21
    > why use ">= 0" instead of "> -1"? Because >= 0 better communicates the intent to humans reading the code. The compiler ought to be be able to optimize that to the equivalent > -1 if doing so would improve performance. – Mark Maslar Jul 31 '09 at 12:53
  • 1
    FastReverse(this IList items) should be FastReverse(this IList items. :) – Rob Sep 16 '10 at 14:03
  • 1
    Splitting sticks 0<=i is even better. After teaching quite a number of kids math over the years, and helped people with coding, I found that it much reduces the errors people make if they ALWAYS swap a>b to b – Eske Rahn Jun 27 '18 at 04:59
20

Before using foreach for iteration, reverse the list by the reverse method:

    myList.Reverse();
    foreach( List listItem in myList)
    {
       Console.WriteLine(listItem);
    }
Prem
  • 630
  • 2
  • 11
  • 25
  • 3
    same as [Matt Howells' answer from '09](https://stackoverflow.com/questions/1211608/possible-to-iterate-backwards-through-a-foreach#answer-1211610) – Martin Schneider Mar 23 '18 at 14:01
  • A word of caution on what `myList` is will be helpful. IEnumerable.Reverse wont work here. – nawfal Jun 26 '18 at 15:10
  • 2
    @MA-Maddin no the two are different. I guess answerer is relying on List.Reverse which is in place. – nawfal Jun 26 '18 at 15:11
  • Actually, I don't know why I said that. I should have added more details... Anyway this is confusing code since `myList` seems to be of type `System.Collections.Generic.List` (or any other custom `List` type) otherwise this code does not work :P – Martin Schneider Jun 26 '18 at 15:47
7

If you use a List<T>, you can also use this code:

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

This is a method that write the list reverse in itself.

Now the foreach:

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

The output is:

3
2
1
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
th3s0urc3
  • 71
  • 1
  • 4
6

Sometimes you don't have the luxury of indexing, or perhaps you want to reverse the results of a Linq query, or maybe you don't want to modify the source collection, if any of these are true, Linq can help you.

A Linq extension method using anonymous types with Linq Select to provide a sorting key for Linq OrderByDescending;

    public static IEnumerable<T> Invert<T>(this IEnumerable<T> source)
    {
        var transform = source.Select(
            (o, i) => new
            {
                Index = i,
                Object = o
            });

        return transform.OrderByDescending(o => o.Index)
                        .Select(o => o.Object);
    }

Usage:

    var eable = new[]{ "a", "b", "c" };

    foreach(var o in eable.Invert())
    {
        Console.WriteLine(o);
    }

    // "c", "b", "a"

It is named "Invert" because it is synonymous with "Reverse" and enables disambiguation with the List Reverse implementation.

It is possible to reverse certain ranges of a collection too, since Int32.MinValue and Int32.MaxValue are out of the range of any kind of collection index, we can leverage them for the ordering process; if an element index is below the given range, it is assigned Int32.MaxValue so that its order doesn't change when using OrderByDescending, similarly, elements at an index greater than the given range, will be assigned Int32.MinValue, so that they appear to the end of the ordering process. All elements within the given range are assigned their normal index and are reversed accordingly.

    public static IEnumerable<T> Invert<T>(this IEnumerable<T> source, int index, int count)
    {
        var transform = source.Select(
            (o, i) => new
            {
                Index = i < index ? Int32.MaxValue : i >= index + count ? Int32.MinValue : i,
                Object = o
            });

        return transform.OrderByDescending(o => o.Index)
                        .Select(o => o.Object);
    }

Usage:

    var eable = new[]{ "a", "b", "c", "d" };

    foreach(var o in eable.Invert(1, 2))
    {
        Console.WriteLine(o);
    }

    // "a", "c", "b", "d"

I'm not sure of the performance hits of these Linq implementations versus using a temporary List to wrap a collection for reversing.


At time of writing, I was not aware of Linq's own Reverse implementation, still, it was fun working this out. https://msdn.microsoft.com/en-us/library/vstudio/bb358497(v=vs.100).aspx

Voxpire
  • 356
  • 6
  • 7
5

Elaborateling slighty on the nice answer by Jon Skeet, this could be versatile:

public static IEnumerable<T> Directional<T>(this IList<T> items, bool Forwards) {
    if (Forwards) foreach (T item in items) yield return item;
    else for (int i = items.Count-1; 0<=i; i--) yield return items[i];
}

And then use as

foreach (var item in myList.Directional(forwardsCondition)) {
    .
    .
}
Eske Rahn
  • 1,137
  • 12
  • 11
4

It is possible if you can change the collection code that implements IEnumerable or IEnumerable (e.g. your own implementation of IList).

Create an Iterator doing this job for you, for example like the following implementation through the IEnumerable interface (assuming 'items' is a List field in this sample):

public IEnumerator<TObject> GetEnumerator()
{
    for (var i = items.Count - 1; i >= 0; i--)
    { 
        yield return items[i];
    }
}

IEnumerator IEnumerable.GetEnumerator()
{
    return GetEnumerator();
}

Because of this your List will iterate in reverse order through your list.

Just a hint: You should clearly state this special behaviour of your list within the documentation (even better by choosing a self-explaining class name like Stack or Queue, too).

Beachwalker
  • 7,685
  • 6
  • 52
  • 94
2

No. ForEach just iterates through collection for each item and order depends whether it uses IEnumerable or GetEnumerator().

Josip Medved
  • 3,631
  • 1
  • 28
  • 36
1

This is simple when we use the List.Reverse() method and foreach together.

 List<int> numbers = new List<int>() { 1, 2, 3, 4, 5, 6, 7 };

        // Reverse the order of the elements            
        foreach (int i in numbers.Reverse())
        {
            // Display the element
            Console.WriteLine(i);
        }            

You can refer to this post for other options as well.

Sabdth
  • 21
  • 2
  • Please be sure to read [Stack Overflow's self-promotion policy](https://stackoverflow.com/help/promotion) when referencing your own content. – Jeremy Caney Jan 20 '23 at 00:14
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 20 '23 at 07:09
0

I added an extension to the list type to help me lazily loop the list in reverse

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

use like this

foreach(var item in list.LazyReverse()){
  // do some work .....
  if(item == somecondition){
     break;// break without loading the reset of the list
  }
}
Eboubaker
  • 618
  • 7
  • 15
-2

I have used this code which worked

                if (element.HasAttributes) {

                    foreach(var attr in element.Attributes().Reverse())
                    {

                        if (depth > 1)
                        {
                            elements_upper_hierarchy_text = "";
                            foreach (var ancest  in element.Ancestors().Reverse())
                            {
                                elements_upper_hierarchy_text += ancest.Name + "_";
                            }// foreach(var ancest  in element.Ancestors())

                        }//if (depth > 1)
                        xml_taglist_report += " " + depth  + " " + elements_upper_hierarchy_text+ element.Name + "_" + attr.Name +"(" + attr.Name +")" + "   =   " + attr.Value + "\r\n";
                    }// foreach(var attr in element.Attributes().Reverse())

                }// if (element.HasAttributes) {
-8

This works pretty well

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

list.Add("Hello");
list.Add("Who");
list.Add("Are");
list.Add("You");

foreach (String s in list)
{
    Console.WriteLine(list[list.Count - list.IndexOf(s) - 1]);
}