web-dev-qa-db-ja.com

各ループのC#はList <T>をどの順序で繰り返しますか?

C#のforeachループが_System.Collections.Generic.List<T>_オブジェクトをループする順序について疑問に思いました。

同じトピックについて 別の質問 を見つけましたが、満足のいく質問に答えているとは感じません。

順序が定義されていないという人がいます。しかし、他の誰かが述べているように、配列を横断する順序は固定されています(0からLength-1まで)。 8.8.4 foreachステートメント

順序を持つ標準クラス(たとえば_List<T>_)にも同じことが言えると言われました。それを裏付けるドキュメントが見つかりません。ですから、今ではそのように動作するかもしれませんが、次の.NETバージョンでは異なる可能性があります。

List(t).Enumerator ドキュメンテーションも見ましたが、運はありません。

別の関連する質問 Javaについては、ドキュメントで具体的に言及されていると述べています:

List.iterator()は、このリスト内の要素を適切な順序で繰り返し処理する反復子を返します。

私はC#のドキュメントでそのようなものを探しています。

前もって感謝します。

編集:すべてのあなたのすべての答えをありがとう(私は非常に多くの返信を得たのに驚いた)。私がすべての答えから理解しているのは、_List<T>_は常にインデックス付けの順序で反復するということです。しかし、 ListのJavaドキュメント と同様に、これを記載した明確なドキュメントを見たいと思っています。

75

On Microsoft Reference Source page for List<T>列挙子は、反復が0からLength-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();
}

それがまだ誰かに関連していることを願っています

2
apokrovskyi

基本的にはIEnumerator実装次第ですが、List<T>の場合は常にリストの自然な順序、つまりインデクサーと同じ順序になります:list[0]list[1]list[2]など。

私はそれが明示的に文書化されているとは思わない-少なくとも、そのような文書を見つけていない-しかし、あなたはそれを保証されたものとして扱うことができると思う。その順序を変更すると、あらゆる種類のコードが無意味に壊れてしまいます。実際、これに従わなかったIList<T>の実装を見て驚いたでしょう。確かに、それが具体的に文書化されているのを見るといいでしょう...

94
Jon Skeet

リンクでは、受け入れられた回答は C#言語仕様バージョン3.0、240ページ

Foreachが配列の要素をトラバースする順序は次のとおりです。1次元配列の場合、要素はインデックス0で始まりインデックスLength – 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.
8
RvdK

順序は、foreachループを使用してデータのコレクションを走査するために使用される反復子によって定義されます。

インデックス可能な標準のコレクション(リストなど)を使用している場合、インデックス0から上に向かってコレクションを走査します。

順序を制御する必要がある場合は、コレクションの反復が 独自のIEnumerableを実装する によって処理される方法を制御するか、foreachループを実行する前にリストを希望どおりに並べ替えることができます。

これは、ジェネリックリストで Enumerator がどのように機能するかを説明しています。最初は、現在の要素は未定義であり、MoveNextを使用して次の項目に移動します。

MoveNext を読んだ場合、コレクションの最初の要素から開始し、そこからコレクションの最後に到達するまで次の要素に移動することを示します。

4
Brendan Enrick

リストは、バッキングストアにある順序でアイテムを返すようです。したがって、リストにリストに追加された場合、その方法で返されます。

プログラムが順序に依存している場合は、リストを走査する前に並べ替えることができます。

線形検索の場合は少しばかげていますが、特定の順序で順序が必要な場合は、その順序でアイテムを作成するのが最善の策です。

1
Broam

私はコードのクイックハックと似たようなことをしなければなりませんでしたが、私がやろうとしていたことに対してはうまくいきませんでしたが、リストを並べ替えました。

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
1
KillJoy