在不使用扩展方法的情况下,使用foreach向后迭代数组
本文关键字:foreach 使用 数组 迭代 情况下 扩展 方法 | 更新日期: 2023-09-27 18:24:51
在谷歌上搜索后,我发现了以下讨论:
可以通过前臂向后迭代吗?
但在答案中使用了扩展方法.Revrse()。使用Reverse,对象列表,例如字符串列表,将首先反转,foreach不会根据我的理解反转列表吗?如果我得到了列表"Cat"、"Dog",并使用.Revrse()-方法,列表将是"Dog"、"Cat",foreach从0元素开始,直到lenght-1-元素,这就是我不想要的。我想知道,如果有任何方法可以反转foreach迭代顺序,从长度-1开始到0。
如果有任何方法可以反转
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);
}