각 루프의 C #은 List <T>에서 어떤 순서로 반복됩니까?


82

C #의 foreach 루프가 System.Collections.Generic.List<T>개체 를 반복하는 순서에 대해 궁금 합니다.

같은 주제에 대한 또 다른 질문을 찾았 지만 만족할만한 답변이 없다고 생각합니다.

누군가는 순서가 정의되지 않았다고 말합니다. 그러나 다른 사람이 말했듯이 배열을 순회하는 순서는 고정되어 있습니다 (0에서 길이 -1까지). 8.8.4 foreach 문

또한 주문 (예 :)이있는 모든 표준 클래스에 대해서도 동일하게 적용됩니다 List<T>. 이를 뒷받침 할 문서를 찾을 수 없습니다. 따라서 지금은 그렇게 작동 할 수 있지만 다음 .NET 버전에서는 다를 수 있습니다 (가능성이 낮더라도).

나는 List(t).Enumerator운없이 문서를 보았습니다 .

또 다른 관련 질문 은 Java의 경우 문서에 구체적으로 언급되어 있습니다.

List.iterator()이 목록의 요소에 대한 반복자를 적절한 순서로 반환합니다. "

C # 문서에서 이와 같은 것을 찾고 있습니다.

미리 감사드립니다.

편집 : 모든 답변에 대해 감사합니다 (얼마나 빨리 답변을 받았는지 놀랍습니다). 모든 답변에서 내가 이해하는 List<T>것은 항상 색인 순서대로 반복 된다는 것 입니다. 하지만 .NET의 Java 문서List 와 유사하게이를 설명하는 문서의 명확한 평화를보고 싶습니다 .

답변:


13

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

누군가에게 여전히 관련이 있기를 바랍니다.


102

기본적으로는 최대의 IEnumerator구현 -하지만를 위해 List<T>항상, 즉 인덱서와 같은 순서로리스트의 자연 순서로 이동합니다 : list[0], list[1],list[2]

나는 그것이 명시 적으로 문서화되었다고 믿지 않는다. 적어도 나는 그러한 문서를 찾지 못했다. 그러나 나는 그것을 보장 된 것으로 취급 할 수 있다고 생각한다. 그 순서를 변경하면 모든 종류의 코드가 무의미하게 손상됩니다. 사실, 나는 IList<T>이것에 불복종하는 어떤 구현을 보면 놀랄 것 입니다. 분명히 그것을 구체적으로 문서화하는 것을 보는 것이 좋을 것입니다 ...


나는 말 그대로 5 초 전에 대답을 확인했고 비슷한 것을 게시하려고했습니다. 당신은 너무 빠릅니다!
Michael G

답장 해 주셔서 감사합니다. 이를 보장하는 문서가 있습니까?
Matthijs Wessels

1
@Michael G : 나는 MSDN 예제 코드를 문서로 사용하지 않을 것입니다. 나는 그것에 너무 많은 끔찍한 오류를 보았다.
Jon Skeet

1
아무도 어레이와 관련하여 동일한 답변을 제공 할 수 있습니까?
yazanpro 2013 년

12
@yazanpro : foreach확실히 배열 순서대로 반복됩니다.
Jon Skeet

8

링크에서 허용되는 답변은 C # 언어 사양 버전 3.0, 페이지 240에 다음 과 같이 나와 있습니다 .

foreach가 배열의 요소를 순회하는 순서는 다음과 같습니다. 1 차원 배열의 경우 색인 0에서 시작하여 색인 길이 – 1로 끝나는 증가하는 색인 ​​순서로 요소가 순회됩니다. 다차원 배열의 경우 요소가 순회됩니다. 가장 오른쪽 차원의 인덱스가 먼저 증가하고 다음 왼쪽 차원이 증가하는 방식으로 왼쪽으로 증가합니다. 다음 예제는 요소 순서로 2 차원 배열의 각 값을 인쇄합니다.

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.

2
예,하지만 이것은 어레 이용입니다. List <T> 클래스도 자동으로 유지합니까?
Matthijs Wessels

2
List <T>는 백업 저장소에 배열을 사용합니다. 네.
Joel Mueller

9
그러나 그것은 구현 세부 사항입니다. List <T>는 배열을 백업 저장소로 사용하는 데 필요 하지 않습니다 .
Eric Lippert

3
List <T> (예제 코드)에 대한 설명서를 지적하고 싶습니다. "List <(Of <(T>)>) 클래스는 ArrayList 클래스와 동일한 일반 클래스입니다. IList <(Of <(T>)>) 필요에 따라 크기가 동적으로 증가 하는 어레이 를 사용하는 일반 인터페이스 . " (강조 내)
RCIX

흠, 나는 항상 배열을 사용한다고 생각합니다. 하지만 그래도 역 열거자를 반환 할 수 없다는 의미입니까?
Matthijs Wessels

4

순서는 foreach 루프를 사용하여 데이터 컬렉션을 순회하는 데 사용되는 반복기에 의해 정의됩니다.

인덱싱 가능한 표준 컬렉션 (예 : 목록)을 사용하는 경우 인덱스 0부터 시작하여 위로 이동하는 컬렉션을 탐색합니다.

순서를 제어해야하는 경우 고유 한 IEnumerable구현하여 컬렉션 반복이 처리되는 방식을 제어 하거나 foreach 루프를 실행하기 전에 원하는 방식으로 목록을 정렬 할 수 있습니다.

이것은 일반 목록에서 열거자가 작동 하는 방식을 설명합니다 . 처음에는 현재 요소가 정의되지 않았으며 MoveNext를 사용하여 다음 항목으로 이동합니다.

MoveNext 를 읽으면 컬렉션의 첫 번째 요소에서 시작하여 컬렉션의 끝에 도달 할 때까지 다음 요소로 이동 함을 나타냅니다.


답장과 추가 해주셔서 감사합니다. 저도 읽었습니다. 나는 단지 <너무 정확하고 싶은 사람을 지정하는 단어>일지도 모르지만, 그들이 "첫 번째 요소"라고 말하면 첫 번째 요소가 아니라 반복 될 첫 번째 요소를 의미한다고 느낍니다. 반복되는 클래스의 순서로.
Matthijs Wessels

예상대로 진행된다는 것이 확실하다면 가장 좋은 방법은 내가 말한대로하고 IEnumerable을 직접 구현하는 것입니다.
Brendan Enrick

1

목록은 백업 저장소에있는 순서대로 항목을 반환하는 것처럼 보이므로 이러한 방식으로 목록에 추가되면 해당 방식으로 반환됩니다.

프로그램이 순서에 의존하는 경우 목록을 탐색하기 전에 정렬 할 수 있습니다.

선형 검색에는 다소 어리석은 일이지만 특정 방식으로 주문이 필요한 경우 해당 순서로 항목을 만드는 것이 가장 좋습니다.


1

내가하려는 일에 대해 작동하지 않았지만 나를 위해 목록을 재정렬 했음에도 불구하고 빠른 코드 해킹과 비슷한 작업을 수행해야했습니다.

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

이것이 질문과 어떤 관련이 있는지 모르겠습니다. 귀하의 코드는 List. 내가 "목록"이 의미하는 바를 오해 한 것 같습니다.
Matthijs Wessels 2012 년

또한의 내용 ColumnsgridColumns먼저 복사하는 이유는 무엇입니까? 당신도 바로 할 수 있다고 생각 :DataGridViewColumn[] gridColumns = dataGridView1.Columns.OrderByDescending(n => n.DisplayIndex).ToArray();
Matthijs Wessels가에게

@MatthijsWessels 원한다면 List를 사용하도록 변경하는 것이 어렵지 않을 것입니다.
Austin Henley 2012 년

@AustinHenley IOrderedEnumerable에 대해 foreach를 수행 할 수 있지만 그게 질문의 내용이 아닙니다. ToArray 대신 ToList를 사용할 수도 있지만 List가 다시 생기고 foreach가 지정된 순서로 항목을 반복할지 여부에 대한 질문은 여전히 ​​답이 없습니다.
Matthijs Wessels 2012 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.