FOREACHによって返されるオブジェクトの順序は安定していますか?
-
03-07-2019 - |
質問
同じコレクションに対する2つのイタレーションが同じ順序でオブジェクトを返すと仮定しても安全ですか?明らかに、コレクションが変更されていないことを前提としています。
解決
簡単な答え-はい。
ただし、コレクションのタイプ(辞書など)によっては、コレクション内のアイテムの順序が挿入された順序と異なる場合があることは明らかです。
ただし、foreachループを使用して、変更されていない単一のコレクションを反復処理するたびに、同じ結果が得られます。
他のヒント
コレクションのタイプに依存します。ほとんどのコレクションでは、答えは<!> quot; Yes <!> quot;です。
ただし、これは保証されていません。コレクションタイプのドキュメントでは、コレクションタイプが指定されているかどうかを指定する必要がありますが、ほとんどの場合、その詳細は見落とされています。ただし、安定していない場合、ドキュメントで言及されていなければ、非常に見落としがちです。
反復しているクラスの具体的な実装を知らない限り、これを保証することはできません。
定義された要素の順序(たとえばList<T>
)を持つコレクションは、安定した順序で列挙されます。
オブジェクトの状態が変わらないコレクションの場合、要素が同じ順序で戻る可能性が高いです。 Dictionary<K,V>
、ただし仕様では保証されていません。
これが当てはまらない例として、テーブルを非同期に圧縮またはサイズ変更するハッシュテーブルベースの辞書実装を想像できます。このような実装は、安定した反復順序を保証しません。
答えは<!>#8220; yes <!>#8221;すべてのビルトインコレクションとおそらくそこにある正気のコレクションクラスの場合、ドキュメントにはIEnumerable
の公式化された制約はありません。したがって、すべての反復が安定していなければならないことは何もわかりません。
次の使用例が想像できます:
foreach (int i in new Shuffler(1, 2, 3, 4, 5, 6, 7, 8, 9))
Console.WriteLine(i);
これは、反復ごとに異なる順序を生成するクラスとして実装される可能性があります。
だから<!>#8211;奇妙な境界線のケースも考慮したい場合、答えは<!>#8220; no <!>#8221;でなければなりません。
通常、要素は同じ順序で返されますが、保証はありません。コレクションクラスの内部実装に完全に依存しています。
たとえば、ランダムな順序で要素を返すように特別に設計されたコレクションクラスのケースを見ることができます。
要するに、コレクションクラスの内部実装を知っていない限り、順序について何も仮定しない。
Linqは、この目的のために IOrderedEnumerable インターフェースを定義しています。
>Re <!> quot; unmodified <!> quot; (NMの返信)-辞書のような多くの複雑なコンテナは順序を保持することを保証しないことに注意してください。アイテムを追加すると、アイテムが最後に表示されることがあり(順序が保持されているという印象を与えます)、場合によっては内部バケットが再編成され、まったく異なる順序になります。
SortedList <!> lt;、<!> gt;のようなものなどには明らかに独自のルールがあります。
ほとんどのコレクションでは、これを想定しても安全です。特定のコレクションに列挙子を非決定的な方法で実装できる可能性の領域を超えていませんが、おそらくそれは起こりません...