93

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

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

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

順序のある標準クラスにも同じことが当てはまるとも言われています(例List<T>)。それをバックアップするためのドキュメントが見つかりません。ですから、今はそのように機能するかもしれませんが、次の.NETバージョンでは異なる可能性があります(可能性は低いかもしれませんが)。

私もList(t).Enumerator運がなくてドキュメントを見ました。

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

List.iterator()このリストの要素に対して適切な順序でイテレータを返します。」

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

前もって感謝します。

編集:すべての回答をありがとうございました(私が非常に多くの返信を受け取ったのは驚くべきことです)。すべての回答から私が理解しているのは、List<T>常にインデックス付けの順序で繰り返されるということです。ただし、のJavaドキュメントListと同様に、これを示すドキュメントの明確な平和を望んでいます。

4

6 に答える 6

107

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

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

于 2009-11-24T14:03:17.307 に答える
28

列挙子の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();
}

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

于 2019-08-16T10:27:54.523 に答える
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.22.33.44.5 5.6 6.77.88.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.
于 2009-11-24T14:10:07.777 に答える
4

順序は、foreachループを使用してデータのコレクションをトラバースするために使用されるイテレーターによって定義されます。

インデックス付け可能な標準コレクション(リストなど)を使用している場合は、インデックス0から始まり、上に向かってコレクションをトラバースします。

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

これは、列挙子が汎用リストに対してどのように機能するかを説明しています。最初、現在の要素は未定義であり、MoveNextを使用して次のアイテムに移動します。

MoveNextを読むと、コレクションの最初の要素から始まり、そこからコレクションの最後に到達するまで次の要素に移動することが示されます。

于 2009-11-24T14:03:58.973 に答える
2

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

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
于 2012-09-18T16:58:51.040 に答える
1

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

プログラムが順序に依存している場合は、リストをトラバースする前にプログラムをソートすることをお勧めします。

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

于 2009-11-24T14:03:47.960 に答える