使用foreach向后迭代数组而不使用扩展方法

时间:2014-09-27 14:47:01

标签: c# arrays iteration

在谷歌搜索后,我发现了这个讨论:

Possible to iterate backwards through a foreach?

但是在答案中有使用扩展方法.Reverse()。反向,对象列表,即。字符串列表,首先要反转,foreach不会以我的理解来反转列表吗?如果我得到了列表" Cat"," Dog",并使用.Reverse() - 方法,列表将是" Dog"," Cat&# 34;和foreach从0元素开始直到lenght-1元素,这就是我不想要的东西。我想知道,如果有任何方法可以反转foreach迭代顺序,从lenght-1开始下降到0.

3 个答案:

答案 0 :(得分:1)

  

如果有任何方法可以反转foreach迭代次序,从长度-1开始下降到0

不适用于List<T>GetEnumerator()的实现返回一个从头到尾枚举的枚举器 - 没有办法覆盖它。

使用自定义集合,您只需使用可以向后移动的其他枚举器,但无法覆盖{{1使用。

答案 1 :(得分:1)

Reverse方法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]; 
} 

但你可以自己做一个扩展方法:

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

然后像这样使用它:

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

或者,当然,你可以做同等的事情:

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

答案 2 :(得分:1)

您可以实现一个向后迭代列表的枚举器。这样,您可以使用foreach而无需更改原始列表或创建副本。

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;
  }

}

用法示例:

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

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