8

想像してみてください

foreach(var item in enumerable)

列挙可能な項目が変わります。現在の foreach に影響しますか?

例:

var enumerable = new List<int>();
enumerable.Add(1);
Parallel.ForEach<int>(enumerable, item =>
{ 
     enumerable.Add(item + 1);
});

それは永遠にループしますか?

4

4 に答える 4

19

通常、例外をスローする必要があります。List<T>GetEnumerator()の実装は、 (Reflector から) メソッドが次のようなEnumerator<T>オブジェクトを提供します。MoveNext()

public bool MoveNext()
{
    List<T> list = this.list;
    if ((this.version == list._version) && (this.index < list._size))
    {
        this.current = list._items[this.index];
        this.index++;
        return true;
    }
    return this.MoveNextRare();
}


private bool MoveNextRare()
{
    if (this.version != this.list._version)
    {
        ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
    }
    this.index = this.list._size + 1;
    this.current = default(T);
    return false;
}

list._version、リストを変更する操作ごとに変更 (増分) されます。

于 2009-07-11T22:08:33.640 に答える
5

列挙子の性質に依存します。コレクションが変更されると、それらの多くは例外をスローします。

たとえば、列挙中にコレクションが変更されList<T>た場合にスローします。InvalidOperationException

于 2009-07-11T22:01:53.577 に答える
2

IEnumerable[and --non -generic names will refer to both]に関する Microsoft のドキュメントでは、これらのインターフェイスを実装するオブジェクトが変更されるたびに、以前に生成された[ ]IEnumerable<T>のインスタンスを無効にすることを推奨しています。. Microsoft のドキュメントにはこのスタンスからの変更が記載されていませんが、実際の の実装はより緩いルールに従っているようです。「賢明に」動作できない場合はスローする必要がありますIEnumeratorIEnumerator<T>InvalidOperationExceptionIEnumerableIEnumeratorInvalidOperationException . 残念ながら、その規則は明示的に述べられておらず、クラスの動作から推測されているため、「賢明な」動作が正確に何を意味するかは明確ではありません。

私が知っているすべての Microsoft クラスは、次の基準を満たさない場合、コレクションが変更されたときに例外をスローします。

  1. 列挙を通じて変更されずに存在するアイテムは、一度だけ返されます。
  2. 列挙中に追加または削除されたアイテムは、多くても 1 回返されますが、列挙中にオブジェクトが削除され、再追加された場合、再追加のたびに新しい「アイテム」が作成されたと見なされる場合があります。
  3. コレクションがソートされた順序で物事を返すことを保証する場合、アイテムが挿入および削除された場合でも、その保証が満たされなければなりません [たとえば、「Fred」がアルファベット順にソートされたリストに追加され、「George」がすでに列挙されている場合、" Fred」は、その列挙中に現れてはなりません]。

コレクションが変更された場合でも上記の基準を満たすことができるかどうかを (例外をスローすることなく) 報告できる何らかの手段があると便利です。たとえば、特定の基準を満たすすべてのアイテムを削除しようとするときに非常に役立つからです。

于 2013-01-27T17:46:40.213 に答える
1

これは、IEnumerable の実装方法に完全に依存します。

リストでは、IllegalOperationException がスローされます。ただし、IEnumarables のこの動作に依存しないでください。一部のループは無限にループし、すぐに OutOfMemoryexception をスローします。

于 2009-07-11T22:01:32.267 に答える