2010-12-31 13 views

答えて

18

は必ずしもToListより速いわけではありません。ちょうどToListを使用してください。

列挙する前の元の配列の要素の数が分からない限り、配列のサイズを変更し、List<T>のように要素を追加することになります。ToArrayは、とにかくList<T>と同じことがあります。さらに、ToListList<T>を返します。これは生の配列よりも優れています。

もちろん、IEnumerable<T>インスタンスの具体的なタイプが分かっている場合は、より高速な方法があるかもしれませんが、それはその点に密接な関係はありません。

サイドノート:配列を使用する必要がない限り、おそらくマイクロ最適化であり、avoidedmost of the timeである必要があります。

+0

これらは事実上同等です。 – Vadim

+0

@ヤード:正確に。 –

+1

+1。実際、Monoの[Enumerable.ToArray'](https://github.com/mono/mono/blob/master/mcs/class/System.Core/System.Linq/Enumerable.cs#L2794)では 'new List 'IEnumerable 'が 'ICollection 'でなければ、(ソース).ToArray() 'が返されます。 MSのものが似ていれば私は驚かないだろう。 –

2

2番目に安価な方法は、new List<T>(myEnumerable).ToArray()と言います。一番安い方法は、.ToArray()(LINQから)、またはC#3.5を使用していない場合は独自のバッファを作成してサイズを倍増させながら追加し、最後にトリムします。

5

Enumerable::ToArrayEnumerable::ToList最終的に内部配列バッファにソースから要素を受信するために、同じ技術を使用して、そのバッファのサイズに達すると、それらは、サイズを2倍、新しいバッファを割り当てるのmemcpy上加算続けますソース上の列挙が完了するまでこのプロセスを繰り返します。最終的な違いは、内部でBuffer<T>の実装を使用するToArrayが正確にサイズがArrayに割り当てられ、結果を返す前に要素をコピーする必要があることです。一方、ToListは、部分的に満たされている可能性がある(おそらく)配列バッファを内部に持つList<T>を返すだけで済みます。

どちらの実装もソースIEnumerableICollectionであれば、彼らは実際に自分のバッファを埋めるために、ソースからICollection::CopyToを使用し、その後ICollection::Countを使用して開始するために、正確な右のバッファサイズを割り当てます最適化を持っています。

最終的にほとんどの状況でほぼ同じように動作しますが、List<T>は技術的には「重い」クラスであり、最終的にはの最後に+ memcpyが割り当てられますソースはICollectionではありません)、正確に正しいサイズの配列を返すことができます。私はたぶんTask::WaitAllのような配列を必要とする何かに結果を渡す必要があることを知っていない限り、通常ToListと固執します。

4

TPLをお持ちであれば.AsParallel().ToList()の可能性を示唆していましたが、私のデュアルコアノートパソコンの非公式テストでは、.ToList()よりも7倍遅くなっています。だから、Mehrdad'sanswerを付けてください。

+1

+1それは潜在的に良い選択肢であり、レシーバオブジェクトの性質によっては、はるかに速くなる可能性がありますが、それは「ポイントに密接に関連しない」カテゴリに該当します。 –

0

私はこれがかなり古いことを知っています...

なぜあなたはこのようなことをすることができませんでしたか?

IEnumerable <T> original = {...挿入するコードをここに挿入...};

IEnumerable <T> copy =(元の選択行の行から)。

実際に必要となるまでコピーとその要素の読み込みを延期する前にこのメソッドを使用していましたが、 "オリジナル"のデータ型をリスト型にキャストしていません。

+0

アイデンティティセレクトでは実際にあなたに何も与えていません。これは、実行時に余分なオーバーヘッドを追加し、潜在的な型にキャストするのを防ぐ以外は、他の 'IEnumerable'への参照をコピーすることと実際には機能的に異なるわけではありません。 'ToList'のある時点でシーケンスがどのように見えるかのスナップショットが必要な場合は、正しい方法です。そうでない場合、他のシーケンスと同じマナーで生成されたシーケンスが必要な場合は、参照自体をコピーしてください。もっと何もする必要はありません。 – Servy

関連する問題