2014-09-27 2 views
0

После выполнения поиска на Google, я нашел это обсуждение:Итерация массив с Еогеасп назад без использования метода расширения

Possible to iterate backwards through a foreach?

Но в ответах есть используется метод расширения .Reverse(). С обратным - список объектов, например. Список строк, сначала будет отменен, и foreach не отменяет список с моим пониманием? Если бы я получил список «Cat», «Dog» и использовал .Reverse() -метод, список будет «Dog», «Cat», а foreach начинается с элемента 0 до элемента lenght-1, и это то, что Я не ищу. Я хотел бы знать, есть ли способ изменить Еогеасп порядок итерации, чтобы начать с длиной-1 до 0.

+0

Если вы действительно есть 'Array' почему уход за' foreach'? Хороший старый 'for' будет делать это хорошо и, вероятно, быстрее, чем любой другой способ. – TaW

+0

Почему бы вам не написать свой собственный (расширенный) метод? То, что вы хотите, не очень распространено и обычно находится в стандартных библиотеках. – Alireza

ответ

1

, есть ли способ обратного foreach итерация порядка, начиная с длины 1- до 0

Не для List<T>. Реализация GetEnumerator() возвращает перечислитель, который перечисляет от начала до конца - нет возможности переопределить это.

С пользовательских коллекции а, то вы бы просто использовать другой перечислитель, может идти в обратном направлении, но нет никакого способа, чтобы переопределить реализацию, List<T> использования.

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 
+0

@DStanley Это несчастливо, но оно * делает * копию даже в этом случае. Посмотрите исходный код в своем ответе. И 'Буфер ' [копирует список] (http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs#2548). –

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); 
} 
+0

Возможно, вы захотите сделать это как 'ICollection ' (или даже 'IReadOnlyCollection ', если это .NET 4.5) вместо 'IList ' он будет совместим с большим количеством вещей, и у вас все еще есть доступ к индексатору , –

+0

@ScottChamberlain: Как вы получаете доступ к элементам по индексу в 'ICollection '? – Guffa

+0

Да, я бы положил деньги на то, что ICollection выставил свойство Index. Сожалею. –

Смежные вопросы