IEnumerable<T>
一部のプログラマーは、 のような実装を渡すよりもパラメーターを渡すほうがよいと主張します。これを行う一般的な理由の 1 つは、他の特定の実装よりもList<T>
多くのコレクションと互換性があるため、より多くのシナリオで API をすぐに使用できることです。IEnumerable<T>
List<T>
マルチスレッド開発シナリオに飛び込むほど、それもIEnumerable<T>
正しいタイプではないと考えるようになり、以下でその理由を説明しようとします。
コレクションの列挙中に次の例外を受け取ったことがありますか?
コレクションが変更されました。列挙操作が実行されない場合があります。(InvalidOperationException)
基本的にこれの原因は、あるスレッドでコレクションが与えられ、他の誰かが別のスレッドでコレクションを変更することです。
この問題を回避するために、次のようにコレクションをメソッド内の配列に変換することで、列挙する前にコレクションのスナップショットを作成する習慣を身につけました。
static void LookAtCollection(IEnumerable<int> collection)
{
foreach (int Value in collection.ToArray() /* take a snapshot by converting to an array */)
{
Thread.Sleep(ITEM_DELAY_MS);
}
}
私の質問はこれです。API を使用するときに呼び出し元がコレクションを配列に変換することを余儀なくされたとしても、原則として列挙型ではなく配列向けにコーディングする方がよいのではないでしょうか?
これはよりクリーンで防弾ではありませんか?(パラメータの型は代わりに配列です)
static void LookAtCollection(int[] collection)
{
foreach (int Value in collection)
{
Thread.Sleep(ITEM_DELAY_MS);
}
}
配列は、列挙可能で固定長であるというすべての要件を満たし、呼び出し元は、その時点でコレクションのスナップショットを操作するという事実を認識しているため、より多くのバグを節約できます。
私が今見つけることができる唯一のより良い代替手段は、コレクションがアイテムコンテンツに関して読み取り専用であるため、さらに防弾となる IReadOnlyCollection です。
編集:
@DanielPryden は、非常に優れた記事「Arrays thinks some有害性」へのリンクを提供しました。そして、作家によるコメントは、「完全に変更可能であると同時にサイズが固定されているという、かなり矛盾した特性を持つコレクションはほとんど必要ありません」および「ほとんどの場合、コレクションよりも優れたツールが使用されます。配列。" アレイは私が望んでいたほど特効薬に近いものではないことを確信しました.リスクと抜け穴に同意します. IReadOnlyCollection<T>
インターフェイスは、配列と の両方よりも優れた代替手段であると思いますが、IEnumerable<T>
今では疑問が残ります。呼び出し先は、IReadOnlyCollection<T>
メソッド宣言のパラメータ型? それとも、コレクションを参照するメソッドにどの実装IEnumerable<T>
を渡すかを呼び出し元が決定できるようにする必要がありますか?
すべての答えをありがとう。これらの回答から多くのことを学びました。