在不使用扩展方法的情况下,使用foreach向后迭代数组

本文关键字:foreach 使用 数组 迭代 情况下 扩展 方法 | 更新日期: 2023-09-27 18:24:51

在谷歌上搜索后,我发现了以下讨论:

可以通过前臂向后迭代吗?

但在答案中使用了扩展方法.Revrse()。使用Reverse,对象列表,例如字符串列表,将首先反转,foreach不会根据我的理解反转列表吗?如果我得到了列表"Cat"、"Dog",并使用.Revrse()-方法,列表将是"Dog"、"Cat",foreach从0元素开始,直到lenght-1-元素,这就是我不想要的。我想知道,如果有任何方法可以反转foreach迭代顺序,从长度-1开始到0。

在不使用扩展方法的情况下,使用foreach向后迭代数组

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

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

对于自定义集合,您只需要使用一个不同的枚举器,可以倒退,但无法覆盖List<T>使用的实现。

Reverse方法将首先复制列表:

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

您可以实现一个枚举器,该枚举器向后遍历列表。这样,您就可以使用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);
}