В каком порядке C# для каждого цикла перебирает List<T>?

StackOverflow https://stackoverflow.com/questions/1790245

  •  22-09-2019
  •  | 
  •  

Вопрос

Мне было интересно, в каком порядке цикл foreach в C# проходит через System.Collections.Generic.List<T> объект.

я нашел Другой вопрос на ту же тему, но я не чувствую, что это дает мне удовлетворительный ответ на мой вопрос.

Кто-то утверждает, что порядок не определен.Но, как утверждает кто-то другой, порядок прохождения массива фиксирован (от 0 до длины-1). 8.8.4 Оператор foreach

Было также сказано, что то же самое справедливо для любых стандартных классов с порядком (например, List<T>).Я не могу найти никакой документации, подтверждающей это.Насколько я знаю, сейчас это может работать так, но, возможно, в следующей версии .NET все будет по-другому (хотя это маловероятно).

Я также посмотрел на List(t).Enumerator документация безуспешно.

Еще один связанный вопрос утверждает, что для Java это специально упоминается в документации:

List.iterator()Возвращает итератор над элементами в этом списке в правильной последовательности ».

Я ищу что-то подобное в документации С#.

Заранее спасибо.

Редактировать:Спасибо вам за все ваши ответы (удивительно, как быстро я получил так много ответов).Из всех ответов я понял, что List<T> всегда выполняет итерацию в порядке индексации.Но мне все же хотелось бы видеть четкую документацию, подтверждающую это, аналогично Документация по Java на List.

Это было полезно?

Решение

На Страница справочного источника Microsoft за List<T> Перечисление явно заявлено, что итерация выполняется от 0 до длины-1:

internal Enumerator(List<T> list) {
    this.list = list;
    index = 0;
    version = list._version;
    current = default(T);
}

public bool MoveNext() {

    List<T> localList = list;

    if (version == localList._version && ((uint)index < (uint)localList._size)) 
    {                                                     
        current = localList._items[index];                    
        index++;
        return true;
    }
    return MoveNextRare();
}

Надеюсь, это все еще актуально для кого -то

Другие советы

В основном это зависит от IEnumerator реализация - но для List<T> он всегда будет идти в естественном порядке списка, т.е.тот же порядок, что и индексатор: list[0], list[1], list[2] и т. д.

Я не верю, что это явно задокументировано — по крайней мере, я не нашел такой документации — но думаю, что вы можете относиться к этому как к гарантии.Любое изменение этого порядка бессмысленно нарушит все виды кода.На самом деле, я был бы удивлен, увидев любую реализацию IList<T> который не подчинился этому.Конечно, было бы неплохо увидеть это конкретно задокументированным...

В вашей ссылке гласит принятый ответ в C# языковая спецификация Версия 3.0, стр. 240:

Приказ, в котором Фореш пересекает элементы массива, выглядит следующим образом: для одномерных массивов элементы пересекаются в порядке увеличения индекса, начиная с индекса 0 и заканчивая длиной индекса-1. Для многомерных массивов элементы пересекаются так что индексы самого правого измерения увеличиваются сначала, затем следующее левое измерение и т. Д. Слева. В следующем примере распечатывает каждое значение в двухмерном массиве, в порядке элемента:

using System;
class Test
{
  static void Main() {
      double[,] values = {
          {1.2, 2.3, 3.4, 4.5},
          {5.6, 6.7, 7.8, 8.9}
      };
      foreach (double elementValue in values)
          Console.Write("{0} ", elementValue);
      Console.WriteLine();
  }
}

Полученная вывод выглядит следующим образом: 1,2 2.3 3.4 4,5 5,6 6,7 7,8 8,9 в примере

int[] numbers = { 1, 3, 5, 7, 9 };
foreach (var n in numbers) Console.WriteLine(n);
the type of n is inferred to be int, the element type of numbers.

Порядок определяется итератором, который используется для прохождения сбора данных с использованием цикла Foreach.

Если вы используете стандартную коллекцию, которая является индексацией (например, список), то она пройдет сбор, начиная с индекса 0 и движется вверх.

Если вам нужно контролировать заказ, вы можете либо контролировать, как обрабатывается итерация коллекции Реализация вашего собственного ienumerable, или вы можете сортировать список так, как вы хотите, прежде чем выполнять петлю Foreach.

Это объясняет, как Перечисление работает в общем списке. Сначала текущий элемент не определен и использует Movenext, чтобы добраться до следующего элемента.

Если вы читаете Movenext Это указывает на то, что он начнется с первого элемента коллекции и оттуда перейдет к следующему, пока не достигнет конца коллекции.

Списки, кажется, возвращают элементы в заказе, которые они находятся в магазине поддержки-так что, если они добавлены в список таким образом, они будут возвращены таким образом.

Если ваша программа зависит от упорядочения, вы можете сортировать ее, прежде чем пройти список.

Это несколько глупо для линейных поисков-но если вам нужен заказ определенным образом, ваш лучший выбор-сделать элементы в таком порядке.

Мне просто пришлось сделать что -то подобное как быстрый взлом кода, хотя это не сработало для того, что я пытался сделать, это изменило список для меня.

Использование LINQ для изменения порядка

         DataGridViewColumn[] gridColumns = new DataGridViewColumn[dataGridView1.Columns.Count];
         dataGridView1.Columns.CopyTo(gridColumns, 0); //This created a list of columns

         gridColumns = (from n in gridColumns
                        orderby n.DisplayIndex descending
                        select n).ToArray(); //This then changed the order based on the displayindex
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top