1

After making a search at the Google, I found this discussion:

Possible to iterate backwards through a foreach?

But in the answers there is used extension method .Reverse(). With reverse, the list of objects, for ie. List of Strings, wtill be reversed first, and foreach doesn't reverse the list with my understoodment? If I got list "Cat", "Dog", and use .Reverse() -method, the list will be "Dog", "Cat", and foreach starts from the 0 element till the lenght-1 -element and that's what I'm not looking for. I would want to know, if there was any way to reverse foreach iteration order, to start from lenght-1 down to 0.

2
  • If you really have an Array why care for foreach? Good old for will do it good'nuff and probably fast than any other way, too. Commented Sep 27, 2014 at 14:50
  • Why don't you write your own (extension) method? What you want is not very common and usual to be in standard libraries. Commented Sep 27, 2014 at 14:50

3 Answers 3

2

if there was any way to reverse foreach iteration order, to start from length-1 down to 0

Not for a List<T>. The implementation of GetEnumerator() returns an enumerator that enumerates from beginning to end - there's no way to override that.

With a custom collection, then you'd just have to use a different enumerator that could go backwards, but there's no way to override the implementation that List<T> uses.

Sign up to request clarification or add additional context in comments.

Comments

1

The Reverse method will copy the list first:

public static IEnumerable<TSource> Reverse<TSource>(this IEnumerable<TSource> source) {
    if (source == null) throw Error.ArgumentNull("source"); 
    return ReverseIterator<TSource>(source);
}

static IEnumerable<TSource> ReverseIterator<TSource>(IEnumerable<TSource> source) { 
    Buffer<TSource> buffer = new Buffer<TSource>(source);
    for (int i = buffer.count - 1; i >= 0; i--) yield return buffer.items[i]; 
} 

But you can do an extension method yourself:

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

And then use it like that:

foreach (var item in array.Backwards())
    Console.WriteLine(item); // Or whatever else

Or, of course, you could just do the equivalent:

for (var i = array.Length - 1; i >= 0; --i)
    Console.WriteLine(array[i]); // Or whatever else

1 Comment

@DStanley This is unfortunate, but it does a copy even in this case. See the source code in my answer. And Buffer<T> copies the list.
1

You can implement an enumerator that iterates though a list backwards. That way you can use foreach without changing the original list or creating a copy of it.

public class ReverseEnumerator<T> : IEnumerator<T> {

  private IList<T> _list;
  private int _index;
  private T _current;

  public ReverseEnumerator(IList<T> list) {
    _list = list;
    Reset();
  }

  public IEnumerator<T> GetEnumerator() {
    return this;
  }

  public T Current {
    get {
      if (_index < 0 && _index >= _list.Count) throw new InvalidOperationException("Enumeration has not started. Call MoveNext.");
      return _current;
    }
  }

  public void Dispose() { }

  object IEnumerator.Current { get { return Current; } }

  public bool MoveNext() {
    bool ok = --_index >= 0;
    if (ok) _current = _list[_index];
    return ok;
  }

  public void Reset() {
    _index = _list.Count;
  }

}

Usage example:

int[] a = { 1, 2, 3, 4, 5 };

foreach (int x in new ReverseEnumerator<int>(a)) {
  Console.WriteLine(x);
}

3 Comments

You might want to do it as a ICollection<T> (or even a IReadOnlyCollection<T> if this is .NET 4.5) instead of a IList<T> it would be compatible with more things and you still have access to the indexer.
@ScottChamberlain: How do you access items by index in an ICollection<T>?
Huh, I would have put money on the fact that ICollection<T> exposed a Index property. Sorry.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.