LINQクエリでToList()またはToArray()を呼び出す方が良いですか?


519

宣言した場所でクエリを正しく評価したい場合がよくあります。私はその上に複数回反復する必要があるので、これは通常、計算が高価です。例えば:

string raw = "...";
var lines = (from l in raw.Split('\n')
             let ll = l.Trim()
             where !string.IsNullOrEmpty(ll)
             select ll).ToList();

これは正常に動作します。しかし、結果を変更しない場合は、ToArray()ではなくをこともできToList()ます。

ただし、はToArray()最初の呼び出しによって実装されるToList()ので、単にを呼び出すよりもメモリ効率が悪いのではないかと思いToList()ます。

私は狂っていますか?私はちょうど呼び出す必要がありToArray()、安全でメモリが二回割り当てられないだろうという知識で安全な- ?


10
.NETの舞台裏で何が起こっているかを知りたい場合は、.NET Reflector
David Hedlund

32
@DavidHedlund .netソースコードをお勧めします
Gqqnbig

1
重要な関係があるにもかかわらず、stackoverflow.com / questions / 6750447 / c-toarray-performanceがこの質問の複製であることには同意しません。メモリ使用量(この質問)とパフォーマンス(他の質問)の両方は、興味深い重要な考慮事項です。それらは個別に説明できますが、どちらを選択するかを決定する際にはどちらも考慮に入れる必要があります。この質問に対する回答のいずれか1つ、またはその他の質問を包括的に推奨することはできません。まとめると、どちらを選ぶかについてのかなり完全な議論を提供するいくつかの答えがあります。
2016

1
@Gqqnbig-これまでで最も役立つコメント!ありがとうございます:-)
マーククーパー

回答:


366

他の制約を満たすために単に配列が必要な場合を除いて、使用する必要がありますToList。ほとんどのシナリオでToArrayは、より多くのメモリが割り当てられますToList

どちらもストレージに配列を使用しますToListが、より柔軟な制約があります。配列は、少なくともコレクション内の要素数と同じ大きさである必要があります。配列が大きい場合は問題ありません。しかしながらToArray、配列のサイズを要素数に正確に合わせる必要があります。

この制約を満たすために、ToArray多くの場合、1つ以上の割り当てが行われToListます。十分な大きさの配列を取得したら、正確なサイズの配列を割り当て、要素をその配列にコピーします。これを回避できるのは、配列の成長アルゴリズムがたまたま格納する必要のある要素の数と一致するときだけです(間違いなく少数派です)。

編集

List<T>値に未使用のメモリが余分にあることの影響について、数人から質問がありました。

これは正当な懸念事項です。作成されたコレクションが長命で、作成後に変更されておらず、Gen2ヒープに到達する可能性が高い場合は、事前に追加の割り当てを行うことをお勧めしますToArray

一般的に私はこれがまれなケースだと思います。ToArray他の短期間のメモリ使用にすぐに渡される多くの呼び出しを確認することははるかに一般的ToListです。その場合は明らかに優れています。

ここで重要なのは、プロファイリング、プロファイリング、そしていくつかのプロファイリングです。


14
一方、配列を作成するためのレッグワークに割り当てられた追加のメモリは、ガベージコレクションの対象になりますが、リストの追加のオーバーヘッドは残りますか?私はそれをよりシンプルに保つと言います。要素を追加または削除する必要がある場合は、そのためのツールがあります。そうでない場合は、そのための別のツールがあります。意味のあるものを使用してください。後で場合は、メモリやパフォーマンスの問題を発見し、これはそれです、それを変更。
Anthony Pegram 2013年

1
@AnthonyPegramはい、それは有効な考慮事項です。値が長期ストレージで使用されており、変更されず、Gen 2に入る可能性がある場合は、Gen 2ヒープを汚染するよりも、追加の割り当てを支払うほうがよい場合があります。私はめったにこれを見ませんが、IME。ToArrayが別の短期間有効なLINQクエリにすぐに渡されるのを見るのがより一般的です。
JaredPar 2013年

2
@AnthonyPegramディスカッションのこちら側を含めるように回答を更新しました
JaredPar

8
@JaredPar 自動スペアの場所ToArrayToList<>明らかにある正確な場所のサイズが必要な場合に、より多くのメモリを割り当てる方法を理解できません。(
自動増加

5
@RoyiNamirは、ToArrayが最初にオーバーヘッドでToListスタイルの割り当てを行い、次に追加の正確なサイズの割り当てを行うためです。
Timbo 2014

169

List<T>は動的サイズの配列として実装されるため、パフォーマンスの違いはわずかです。いずれかの呼び出しToArray()(内部使用するBuffer<T>配列を成長させるクラス)またはToList()呼び出します(List<T>(IEnumerable<T>)コンストラクタ)を配列にそれらを入れて、それはそれらをすべて収まるまで、配列を成長させる事になってしまうでしょう。

この事実を具体的に確認したい場合は、Reflectorで問題のメソッドの実装を確認してください。ほとんど同じコードにまとめられていることがわかります。


2
私が遭遇した興味深い事実は、プロジェクションでグループ結合によって定義されたグループを使用して引き起こされた相関クエリの場合、LinqがSQLに別のサブクエリを追加して、そのグループのカウントを取得することです。これは、これらの場合、アイテムが取得される前にコレクションのサイズがわかるため、正確なサイズの配列を直接作成でき、結果を具体化しながら処理リソースとメモリリソースを節約できることを意味します。
jpierson

133
カウントが事前にわかっている場合、パフォーマンスは同じです。カウントが事前に知られていない場合は、唯一の違いToArray()とは、ToList()前者が後者は過剰トリミングしないのに対し、配列全体をコピーすることを含む過剰を、トリミングしなければならないことであるが、25の平均値を使用しより多くのメモリ。これは、データ型が大きい場合にのみ影響しますstruct。ただ考えるための食べ物。
スコットリッピー

9
@EldritchConundrum 25%はこのロジックに由来します:アイテムの数が不明な場合、呼び出しを行うToListToArray、小さなバッファーを作成することから始めます。そのバッファーがいっぱいになると、バッファーの容量が2倍になり、続行されます。容量は常に2倍になるため、未使用のバッファーは常に0%から50%の間になります。
スコットリッピー2013

2
@ScottRippey IEnumerableソースから新しいリストのソースを検索し、IEnumerableがICollectionであるかどうかを確認し、ICollectionである場合は、Countプロパティから必要な正確なサイズの配列を1つ割り当てることから始めます。 ToList()が間違いなく高速になるケースです。完全な答えにはその事実が含まれる可能性がありますが、それは最も一般的なケースではないと思います。
AndyClaw 2014年

3
両方の@AndyClaw ListBufferをチェックするICollectionその場合、性能は同じであろう。
Scott Rippey 2014年

54

(7年後...)

他のいくつかの(良い)答えは、発生する微視的なパフォーマンスの違いに集中しています。

このポストは、言及するだけのサプリメントであるセマンティック差との間に存在するIEnumerator<T>(アレイによって生成さT[]Aによって返されたものと比較して)をList<T>です。

例によって最もよく示される:

IList<int> source = Enumerable.Range(1, 10).ToArray();  // try changing to .ToList()

foreach (var x in source)
{
  if (x == 5)
    source[8] *= 100;
  Console.WriteLine(x);
}

上記のコードは例外なく実行され、出力が生成されます。

1
2
3
4
5
6
7
8
900
10

この番組IEnumarator<int>で返されるint[]配列は、列挙の作成以降に変更されているかどうかを追跡しません。

ローカル変数をsourceとして宣言したことに注意してくださいIList<int>。このようにして、C#コンパイラーがforeachステートメントをfor (var idx = 0; idx < source.Length; idx++) { /* ... */ }ループに相当するものに最適化しないようにします。これは、var source = ...;代わりに使用した場合にC#コンパイラが行う可能性があることです。私の現在のバージョンの.NETフレームワークでは、ここで使用される実際の列挙子は非公開の参照型ですSystem.SZArrayHelper+SZGenericArrayEnumerator`1[System.Int32]が、もちろんこれは実装の詳細です。

ここで、に変更.ToArray()すると.ToList()、次のようになります。

1
2
3
4
5

続いて、System.InvalidOperationException次のような発言が続きます。

コレクションが変更されました。列挙操作が実行されない可能性があります。

この場合の基礎となる列挙子は、パブリックな可変値型ですSystem.Collections.Generic.List`1+Enumerator[System.Int32]IEnumerator<int>この場合はを使用するため、この場合はボックス内にボックス化されていますIList<int>)。

結論として、によって生成された列挙子、列挙List<T>中にリストが変更されたかどうかを追跡しますが、によって生成された列挙子は変更しT[]ません。したがって、とを選択するときは.ToList()、この違いを考慮してください.ToArray()

多くの場合、列挙子の存続期間中に変更されたかどうかを追跡するコレクションを1つ追加し .ToArray()たり.ToList()、回避したりします。

(誰もが知りたい場合はどのようにList<>コレクションが変更されたかどうかを追跡し、民間分野がある_versionたびに変更され、このクラスでList<>更新されますが。)


28

@mquanderのパフォーマンスの違いは重要ではないことに同意します。しかし、私はそれを確実にベンチマークしたかったので、私はそうしました-そして、それは重要ではありません。

Testing with List<T> source:
ToArray time: 1934 ms (0.01934 ms/call), memory used: 4021 bytes/array
ToList  time: 1902 ms (0.01902 ms/call), memory used: 4045 bytes/List

Testing with array source:
ToArray time: 1957 ms (0.01957 ms/call), memory used: 4021 bytes/array
ToList  time: 2022 ms (0.02022 ms/call), memory used: 4045 bytes/List

各ソース配列/リストには10​​00個の要素がありました。したがって、時間とメモリの違いはごくわずかであることがわかります。

私の結論:数バイトのメモリが本当に重要でない限り、は配列よりも多くの機能を提供するため、ToList()を使用List<T>することもできます。


1
structプリミティブ型またはクラスの代わりにラージを使用した場合、この結果は異なるのでしょうか。
Scott Rippey、

12
List <T> .ToList ???? どういう意味?IEnumerableをそれに与えようとすると、ICollectionインターフェイスは実装されません。
グリゴリー

8
ToListor ToArray呼び出しの時間のみを測定し、いずれの列挙も測定しないようにしたかったのですIEnumerable。List <T> .ToList()は引き続き新しいList <T>を作成します-単に「これを返す」だけではありません。
EMP

23
-1 パラメータが指定された場合の動作ToArray()とのToList()違いが大きすぎるICollection<T>-単一の割り当てと単一のコピー操作を実行するだけです。どちらList<T>Array実装ICollection<T>あなたのベンチマークは、すべてでは有効ではありませんので、。
Mohammad Dehghan 2014

1
興味のある方のために、独自のベンチマークを別の回答として投稿しました。これは.Select(i => i)ICollection<T>実装の問題を回避するために使用さIEnumerable<>れ、最初にソースを反復するのにどれだけの時間がかかっているかを確認するためのコントロールグループが含まれています。
StriplingWarrior 2017

19

ToList()IEnumerable<T>(たとえばORMから)を使用する場合は、通常は推奨されます。シーケンスの長さが最初にわからない場合は、ToArray()Listのような動的な長さのコレクションを作成し、それを配列に変換するため、余分な時間がかかります。


26
この場合、読みやすさがパフォーマンスよりも優れていると判断しました。要素の追加を続けると予想される場合にのみ、ToListを使用します。他のすべての場合(ほとんどの場合)では、ToArrayを使用します。しかし、入力をありがとう!
フランク・クルーガー、2010

5
ILSpyを見て、をEnumerable.ToArray()呼び出しますnew Buffer<TSource>(source).ToArray()。Bufferコンストラクターでは、ソースがICollectionを実装している場合、source.CopyTo(items、0)を呼び出し、次に.ToArray()が内部項目配列を直接返します。したがって、その場合、余分な時間がかかる変換はありません。ソースがICollectionを実装していない場合、上記のScott Rippeyのコメントで説明されているように、配列の末尾から余分な未使用の位置を削除するために、ToArrayは配列のコピーになります。
BrandonAGr 2013年

19

メモリは常に2回割り当てられます-またはそれに近いもの。配列のサイズを変更できないため、どちらの方法でも、何らかのメカニズムを使用して、増大するコレクションのデータを収集します。(まあ、リストはそれ自体成長しているコレクションです。)

リストはアレイを内部ストレージとして使用し、必要に応じて容量を2倍にします。これは、平均して、アイテムの2/3が少なくとも1回再割り当てされ、アイテムの半分が少なくとも2回再割り当てされ、アイテムの半分が少なくとも3回再割り当てされていることを意味します。つまり、各アイテムは平均で1.3回再割り当てされており、オーバーヘッドはそれほど大きくありません。

また、文字列を収集する場合、コレクション自体には文字列への参照のみが含まれ、文字列自体は再割り当てされないことにも注意してください。


これは無知な質問かもしれませんが、概説する2 / 3、1 / 3、1 / 6ロジックは、リストの配列を適切に拡張できると想定していませんか?つまり、配列の最後に空きスペースがあるので、既存の割り当てを移動する必要はありませんか?

@JonofAllTrades:いいえ、配列が適切に拡張されることはありません。.NETのメモリ管理は、それを実行しません。それが適切に拡張される場合、アイテムの再割り当ては必要ありません。
Guffa 2013

ああ、そうです。再割り当てされていないアイテムは、最終割り当てに含まれていたため、そうする必要はありませんでした。以前の割り当てで割り当てられたすべてのアイテムが移動されますが、配列の長さが対数的に増加するため、これは計算可能な部分です。明確にしていただきありがとうございます!

19

それは2020年の外であり、誰もが.NET Core 3.1を使用しているので、Benchmark.NETでいくつかのベンチマークを実行することにしました。

TL; DR:ToArray()の方がパフォーマンスが優れており、コレクションを変更する予定がない場合は、意図を伝える作業が改善されます。


    [MemoryDiagnoser]
    public class Benchmarks
    {
        [Params(0, 1, 6, 10, 39, 100, 666, 1000, 1337, 10000)]
        public int Count { get; set; }

        public IEnumerable<int> Items => Enumerable.Range(0, Count);

        [Benchmark(Description = "ToArray()", Baseline = true)]
        public int[] ToArray() => Items.ToArray();

        [Benchmark(Description = "ToList()")]
        public List<int> ToList() => Items.ToList();

        public static void Main() => BenchmarkRunner.Run<Benchmarks>();
    }

結果は次のとおりです。


    BenchmarkDotNet=v0.12.0, OS=Windows 10.0.14393.3443 (1607/AnniversaryUpdate/Redstone1)
    Intel Core i5-4460 CPU 3.20GHz (Haswell), 1 CPU, 4 logical and 4 physical cores
    Frequency=3124994 Hz, Resolution=320.0006 ns, Timer=TSC
    .NET Core SDK=3.1.100
      [Host]     : .NET Core 3.1.0 (CoreCLR 4.700.19.56402, CoreFX 4.700.19.56404), X64 RyuJIT
      DefaultJob : .NET Core 3.1.0 (CoreCLR 4.700.19.56402, CoreFX 4.700.19.56404), X64 RyuJIT


    |    Method | Count |          Mean |       Error |      StdDev |        Median | Ratio | RatioSD |   Gen 0 | Gen 1 | Gen 2 | Allocated |
    |---------- |------ |--------------:|------------:|------------:|--------------:|------:|--------:|--------:|------:|------:|----------:|
    | ToArray() |     0 |      7.357 ns |   0.2096 ns |   0.1960 ns |      7.323 ns |  1.00 |    0.00 |       - |     - |     - |         - |
    |  ToList() |     0 |     13.174 ns |   0.2094 ns |   0.1958 ns |     13.084 ns |  1.79 |    0.05 |  0.0102 |     - |     - |      32 B |
    |           |       |               |             |             |               |       |         |         |       |       |           |
    | ToArray() |     1 |     23.917 ns |   0.4999 ns |   0.4676 ns |     23.954 ns |  1.00 |    0.00 |  0.0229 |     - |     - |      72 B |
    |  ToList() |     1 |     33.867 ns |   0.7350 ns |   0.6876 ns |     34.013 ns |  1.42 |    0.04 |  0.0331 |     - |     - |     104 B |
    |           |       |               |             |             |               |       |         |         |       |       |           |
    | ToArray() |     6 |     28.242 ns |   0.5071 ns |   0.4234 ns |     28.196 ns |  1.00 |    0.00 |  0.0280 |     - |     - |      88 B |
    |  ToList() |     6 |     43.516 ns |   0.9448 ns |   1.1949 ns |     42.896 ns |  1.56 |    0.06 |  0.0382 |     - |     - |     120 B |
    |           |       |               |             |             |               |       |         |         |       |       |           |
    | ToArray() |    10 |     31.636 ns |   0.5408 ns |   0.4516 ns |     31.657 ns |  1.00 |    0.00 |  0.0331 |     - |     - |     104 B |
    |  ToList() |    10 |     53.870 ns |   1.2988 ns |   2.2403 ns |     53.415 ns |  1.77 |    0.07 |  0.0433 |     - |     - |     136 B |
    |           |       |               |             |             |               |       |         |         |       |       |           |
    | ToArray() |    39 |     58.896 ns |   0.9441 ns |   0.8369 ns |     58.548 ns |  1.00 |    0.00 |  0.0713 |     - |     - |     224 B |
    |  ToList() |    39 |    138.054 ns |   2.8185 ns |   3.2458 ns |    138.937 ns |  2.35 |    0.08 |  0.0815 |     - |     - |     256 B |
    |           |       |               |             |             |               |       |         |         |       |       |           |
    | ToArray() |   100 |    119.167 ns |   1.6195 ns |   1.4357 ns |    119.120 ns |  1.00 |    0.00 |  0.1478 |     - |     - |     464 B |
    |  ToList() |   100 |    274.053 ns |   5.1073 ns |   4.7774 ns |    272.242 ns |  2.30 |    0.06 |  0.1578 |     - |     - |     496 B |
    |           |       |               |             |             |               |       |         |         |       |       |           |
    | ToArray() |   666 |    569.920 ns |  11.4496 ns |  11.2450 ns |    571.647 ns |  1.00 |    0.00 |  0.8688 |     - |     - |    2728 B |
    |  ToList() |   666 |  1,621.752 ns |  17.1176 ns |  16.0118 ns |  1,623.566 ns |  2.85 |    0.05 |  0.8793 |     - |     - |    2760 B |
    |           |       |               |             |             |               |       |         |         |       |       |           |
    | ToArray() |  1000 |    796.705 ns |  16.7091 ns |  19.8910 ns |    796.610 ns |  1.00 |    0.00 |  1.2951 |     - |     - |    4064 B |
    |  ToList() |  1000 |  2,453.110 ns |  48.1121 ns |  65.8563 ns |  2,460.190 ns |  3.09 |    0.10 |  1.3046 |     - |     - |    4096 B |
    |           |       |               |             |             |               |       |         |         |       |       |           |
    | ToArray() |  1337 |  1,057.983 ns |  20.9810 ns |  41.4145 ns |  1,041.028 ns |  1.00 |    0.00 |  1.7223 |     - |     - |    5416 B |
    |  ToList() |  1337 |  3,217.550 ns |  62.3777 ns |  61.2633 ns |  3,203.928 ns |  2.98 |    0.13 |  1.7357 |     - |     - |    5448 B |
    |           |       |               |             |             |               |       |         |         |       |       |           |
    | ToArray() | 10000 |  7,309.844 ns | 160.0343 ns | 141.8662 ns |  7,279.387 ns |  1.00 |    0.00 | 12.6572 |     - |     - |   40064 B |
    |  ToList() | 10000 | 23,858.032 ns | 389.6592 ns | 364.4874 ns | 23,759.001 ns |  3.26 |    0.08 | 12.6343 |     - |     - |   40096 B |

    // * Hints *
    Outliers
      Benchmarks.ToArray(): Default -> 2 outliers were removed (35.20 ns, 35.29 ns)
      Benchmarks.ToArray(): Default -> 2 outliers were removed (38.51 ns, 38.88 ns)
      Benchmarks.ToList(): Default  -> 1 outlier  was  removed (64.69 ns)
      Benchmarks.ToArray(): Default -> 1 outlier  was  removed (67.02 ns)
      Benchmarks.ToArray(): Default -> 1 outlier  was  removed (130.08 ns)
      Benchmarks.ToArray(): Default -> 1 outlier  was  detected (541.82 ns)
      Benchmarks.ToArray(): Default -> 1 outlier  was  removed (7.82 us)

    // * Legends *
      Count     : Value of the 'Count' parameter
      Mean      : Arithmetic mean of all measurements
      Error     : Half of 99.9% confidence interval
      StdDev    : Standard deviation of all measurements
      Median    : Value separating the higher half of all measurements (50th percentile)
      Ratio     : Mean of the ratio distribution ([Current]/[Baseline])
      RatioSD   : Standard deviation of the ratio distribution ([Current]/[Baseline])
      Gen 0     : GC Generation 0 collects per 1000 operations
      Gen 1     : GC Generation 1 collects per 1000 operations
      Gen 2     : GC Generation 2 collects per 1000 operations
      Allocated : Allocated memory per single operation (managed only, inclusive, 1KB = 1024B)
      1 ns      : 1 Nanosecond (0.000000001 sec)

1
あなたは、コレクションを変異させることを計画していない場合は、私が思うだろうより良いと示すことが意図缶ToImmutableArray()(System.Collections.Immutableパッケージから)😉
アルトゥーロ・トレス・サンチェス

@ArturoTorresSáncheztrueですが、コレクションがメソッドの外部に公開されていない場合は、配列を使用します。
Tyrrrz

2
これをありがとう。選ばれた答えは単なる議論であり、その議論に続く結果を想定しています。これを科学的に行うと、おまけとしてどれだけの違いがあるかを知るために、実際に知る方法は1つしかありません。
ジョナス

15

編集:この回答の最後の部分は無効です。しかし、残りはまだ有用な情報なので、それは残しておきます。

私はこれが古い投稿であることを知っていますが、同じ質問をしていくつかの調査を行った後、共有する価値があるかもしれない興味深いものを見つけました。

まず、@ mquanderとその回答に同意します。彼はパフォーマンスに関しては、2つは同一であると言って正しいです。

ただし、System.Linq.EnumerableExtensions名前空間のメソッドを確認するためにReflectorを使用しており、非常に一般的な最適化に気づきました。
可能な限り、IEnumerable<T>ソースはメソッドにキャストされるIList<T>ICollection<T>、メソッドを最適化します。たとえば、を見てくださいElementAt(int)

興味深いことに、Microsoftは唯一の最適化のために選んだのIList<T>ではなくIList。MicrosoftはこのIList<T>インターフェースの使用を好むようです。

System.Arrayはを実装するだけなIListので、これらの拡張機能の最適化によるメリットはありません。
したがって、私は、この.ToList()方法を使用することがベストプラクティスであると私は考えます。
拡張メソッドのいずれかを使用する場合、またはリストを別のメソッドに渡す場合、それがに最適化される可能性がありIList<T>ます。


16
私はテストをして、驚くべきことを見つけました。配列はIList <T>を実装します!Reflectorを使用してSystem.Arrayを分析すると、IList、ICollection、IEnumerableの継承チ​​ェーンのみが表示されますが、ランタイムリフレクションを使用すると、string []にIList、ICollection、IEnumerable、IList <string>、ICollection <stringの継承チェーンがあることがわかりました>、IEnumerable <string>。したがって、@ mquanderよりも良い答えはありません!
Scott Rippey、2010

@ScottRippeyはい。あなたが気付いた奇妙な観察は、実際には「ハック」の一部です-「固定サイズ」と同様のプロパティに関しても、かなり奇妙な意味があります(キャスト方法によっては不整合があります)。.netソースコード内のこの主題に触れるかなり大きなコメントがいくつかあります。リンクしていないのは残念ですが、私が正しく覚えていれば、(配列クラス内で)見つけるのは非常に簡単です。(そして、矛盾について議論する大きなSOの質問もあります...どこか...> __>)
AnorZaken

@ScottRippey FYY私はあなたのコメントに関係するこの答えを見つけました:stackoverflow.com/a/4482567/2063755
David Klempfner '10

14

ここで行った他のベンチマークが不足していることがわかりました。私の方法論に問題がある場合はお知らせください。

/* This is a benchmarking template I use in LINQPad when I want to do a
 * quick performance test. Just give it a couple of actions to test and
 * it will give you a pretty good idea of how long they take compared
 * to one another. It's not perfect: You can expect a 3% error margin
 * under ideal circumstances. But if you're not going to improve
 * performance by more than 3%, you probably don't care anyway.*/
void Main()
{
    // Enter setup code here
    var values = Enumerable.Range(1, 100000)
        .Select(i => i.ToString())
        .ToArray()
        .Select(i => i);
    values.GetType().Dump();
    var actions = new[]
    {
        new TimedAction("ToList", () =>
        {
            values.ToList();
        }),
        new TimedAction("ToArray", () =>
        {
            values.ToArray();
        }),
        new TimedAction("Control", () =>
        {
            foreach (var element in values)
            {
                // do nothing
            }
        }),
        // Add tests as desired
    };
    const int TimesToRun = 1000; // Tweak this as necessary
    TimeActions(TimesToRun, actions);
}


#region timer helper methods
// Define other methods and classes here
public void TimeActions(int iterations, params TimedAction[] actions)
{
    Stopwatch s = new Stopwatch();
    int length = actions.Length;
    var results = new ActionResult[actions.Length];
    // Perform the actions in their initial order.
    for (int i = 0; i < length; i++)
    {
        var action = actions[i];
        var result = results[i] = new ActionResult { Message = action.Message };
        // Do a dry run to get things ramped up/cached
        result.DryRun1 = s.Time(action.Action, 10);
        result.FullRun1 = s.Time(action.Action, iterations);
    }
    // Perform the actions in reverse order.
    for (int i = length - 1; i >= 0; i--)
    {
        var action = actions[i];
        var result = results[i];
        // Do a dry run to get things ramped up/cached
        result.DryRun2 = s.Time(action.Action, 10);
        result.FullRun2 = s.Time(action.Action, iterations);
    }
    results.Dump();
}

public class ActionResult
{
    public string Message { get; set; }
    public double DryRun1 { get; set; }
    public double DryRun2 { get; set; }
    public double FullRun1 { get; set; }
    public double FullRun2 { get; set; }
}

public class TimedAction
{
    public TimedAction(string message, Action action)
    {
        Message = message;
        Action = action;
    }
    public string Message { get; private set; }
    public Action Action { get; private set; }
}

public static class StopwatchExtensions
{
    public static double Time(this Stopwatch sw, Action action, int iterations)
    {
        sw.Restart();
        for (int i = 0; i < iterations; i++)
        {
            action();
        }
        sw.Stop();

        return sw.Elapsed.TotalMilliseconds;
    }
}
#endregion

LINQPadスクリプトはこちらからダウンロードできます

結果: ToArrayとToListのパフォーマンス

上記のコードを調整すると、次のことがわかります。

  1. 小さな配列を扱う場合、違いはそれほど重要ではありません。 より多くの反復が、より小さな配列
  2. intではなくs を扱う場合、違いはそれほど重要ではありません。string
  3. structsの代わりに大きなs を使用するstringと、一般に多くの時間がかかりますが、比率はあまり変わりません。

これは、上位投票の回答の結論に同意します。

  1. コードが大量のデータのリストを頻繁に生成しない限り、パフォーマンスの違いに気付くことはほとんどありません。(100Kストリングのリストを1000個ずつ作成した場合、200ミリ秒しか差がありませんでした。)
  2. ToList() 一貫して高速に実行されるため、結果を長期間保持することを計画していない場合は、より良い選択です。

更新

@JonHannaは、実装によってSelectは、ToList()またはToArray()実装が結果のコレクションのサイズを事前に予測できることを指摘しました。.Select(i => i)上記のコードで置き換えると、現時点ではWhere(i => true) 非常によく似た結果得られ、.NET実装に関係なくそうする可能性が高くなります。

SelectではなくWhereを使用したベンチマーク


それはサイズがあることを行っている実感ますので、.NETのコアでは両方のケースでは、より良いここnetfxによりべきである100000と最適化するために、使用することを両方ToList()ToArray()して、ToArray()それが必要になり、それが縮小操作を必要としないので、非常にわずかに軽量であることそれ以外の場合は、1つの場所ToList()に利点があります。問題の例は、そのWhereようなサイズ予測を行うことができないという意味で、まだ失われます。
Jon Hanna

@JonHanna:迅速なフィードバックをありがとう。.NET Coreがその最適化を行っていることは知りませんでした。カッコいい。私のコードで.Select(i => i).Where(i => true)、それを修正するために置き換えることができます。
StriplingWarrior 2017

はい、corefxに影響を与える最適化を停止します。ToArray()上記のように、2の累乗のサイズ(有利になるはず)とそうでないサイズの両方を用意し、結果を比較するのは興味深いかもしれません。
Jon Hanna

@JonHanna:興味深いことに、ベストケースのシナリオではToArray() まだ負けています。Math.Pow(2, 15)(:700ms、てToArray:900ms ToListメソッド)の要素、それはです。もう1つの要素を追加すると、要素がバンプされます(ToList:925、ToArray:1350)。場合、私は疑問に思うToArrayまだそれがすでに最適なサイズだとしても、配列をコピーしていますか?彼らはおそらく、それが特別な条件に値しないほどのまれな出来事であると考えました。
StriplingWarrior 2017

corefxで最適化を開始する前でも、正確なサイズの一致はコピーされなかったため、最大の中断が発生します。
Jon Hanna

12

行くか、理想的にはデザインの選択が何であるToListかにToArray基づいて決定する必要があります。インデックスによってのみ反復およびアクセスできるコレクションが必要な場合は、を選択しますToArray。後で簡単にコレクションに追加したりコレクションから削除したりする追加の機能が必要な場合は、ToList(実際に配列に追加できないというわけではありませんが、通常は適切なツールではありません)。

パフォーマンスが重要な場合は、操作を高速化する方法も検討する必要があります。現実的に、あなたは呼んで文句を言わないToListか、ToArray百万回、しかし、可能性が得られ、コレクションに百万回動作します。ある程度のオーバーヘッドがある[]ので、その点では優れています。効率の比較については、このスレッドを参照してください。どちらがより効率的か:List <int>またはint []List<>[]

少し前の自分のテストでは、私はToArrayより速く発見していました。そして、テストがどの程度歪んでいたのかはわかりません。ただし、パフォーマンスの違いはそれほど大きくありません。これは、これらのクエリを何百万回もループで実行している場合にのみ顕著になります。


2
はい-コンパイラが(IEnumerable <>ではなく)配列を反復していることを認識している場合は、反復を大幅に最適化できます。
RobSiklos 2013

12

非常に遅い答えですが、それはグーグルのために役立つと思います。

どちらもlinqを使用して作成された場合に問題があります。どちらも、必要に応じて同じコードを実装してバッファのサイズ変更します。ToArray内部的にクラスを使用して、IEnumerable<>4つの要素の配列を割り当てることにより、配列に変換します。それが十分でない場合は、新しい配列を作成して現在のサイズを2倍にし、現在の配列をそれにコピーすることによってサイズを2倍にします。最後に、アイテム数の新しい配列を割り当てます。クエリが129要素を返す場合、ToArrayは6つの割り当てとメモリコピー操作を行って256要素の配列を作成し、次に129の別の配列を返します。メモリ効率のためにそんなに。

ToListも同じことを行いますが、後で項目を追加できるため、最後の割り当てをスキップします。リストは、linqクエリから作成されたか、手動で作成されたかは関係ありません。

作成の場合、Listはメモリでは優れていますが、CPUではより悪いです。なぜなら、listは一般的なソリューションであるため、すべてのアクションでは、配列の.netの内部範囲チェックに加えて範囲チェックが必要です

したがって、結果セットを何度も繰り返し処理する場合は、配列よりも範囲のチェックが少なくなるため配列が適切であり、コンパイラは通常、シーケンシャルアクセス用に配列を最適化します。

リストを作成するときに容量パラメーターを指定すると、リストの初期化割り当てを改善できます。この場合、結果のサイズがわかっていれば、配列は1回だけ割り当てられます。ToListof linqはそれを提供するためのオーバーロードを指定していません。そのため、指定された容量でリストを作成し、を使用する拡張メソッドを作成する必要がありますList<>.AddRange

この回答を完了するには、次の文章を書く必要があります

  1. 最後に、ToArrayまたはToListのいずれかを使用できます。パフォーマンスはそれほど変わりません(@EMPの回答を参照)。
  2. C#を使用しています。パフォーマンスが必要な場合は、パフォーマンスの高いコードを書くことを心配しないでください。ただし、パフォーマンスの悪いコードを書かないことを心配してください。
  3. 高性能コードの場合は常にx64をターゲットにします。AFAIK、x64 JITはC ++コンパイラに基づいており、末尾再帰の最適化などの面白いことをいくつか実行します。
  4. 4.5では、プロファイルに基づく最適化とマルチコアJITを楽しむこともできます。
  5. 最後に、非同期/待機パターンを使用して、より速く処理できます。

彼らは両方吸う?冗長なメモリ割り当てを必要としない別のアイデアがありますか?
nawfal 2013年

質問のコンテキストでは、はい、どちらも問題がありますが、冗長な割り当てのためであり、それ以外には何もありません。冗長な割り当てを減らすために、メモリと反復速度を犠牲にしてリンクリストを使用できます。結局のところ、これは私たちが行うことであり、トレードオフを行います。容量が200のリストを作成して(たとえば)、アイテムをロードする場合の別のアイデア。これにより冗長性も低下しますが、アレイは常に高速であるため、これはもう1つのトレードオフです。
Erdogan Kurtur 2013年

200のリストを作成しますか?これサイズ変更を回避するかもしれませんが、使用されている冗長メモリについて話していました。サイズが何であるかについて事前の知識がないので、あなたはそれを助けることができません。容量はのコンストラクタですでに指定できますが、指定List<T>しない場合や指定できない場合は、それを支援することはできません。
nawfal 2013年

2
メモリ内の唯一の冗長データは、ポインタのリスト(この場合)である配列の内容です。100万個の64ビットポインターは、8 MBものメモリを必要とします。これは、それらが指す100万個のオブジェクトと比較して何もありません。200は単なる数値であり、サイズ変更の呼び出し回数を最大5倍削減する可能性があります。はい、私たちはそれを助けることはできません。より良いオプションはありません。私にはこれ以上の解決策はありませんが、これは問題がどこにあるかを言うことを許されないという意味ではありません。
Erdogan Kurtur 2013年

1
結局それはあなたが線を引くところです。私は現在の実装が好きです。あなたの答えの口調は、問題がどこにあるかというよりむしろ批判だと私に思わせました:)
nawfal

7

これは古い質問ですが、それに遭遇したユーザーの利益のために、Enumerableを「メモ化」する代わりに、ToArray()であるLinqステートメントの複数の列挙をキャッシュして停止するという効果もあります。 ToList()は、リストまたは配列のコレクション属性が使用されることはありませんが、多くの場合に使用されます。

MemoizeはRX / System.Interactive libで利用でき、ここで説明されています: System.Interactiveを使用したその他のLINQ

(Linq to Objectsを頻繁に使用している場合に強くお勧めするBart De'Smetのブログから)


4

1つのオプションは、読み取り専用 を返す独自の拡張メソッドを追加することICollection<T>です。これは、使用するよりも改善することができますToListまたはToArrayあなたは、配列/リストのインデックスプロパティのいずれかを使用するか、またはリストから/削除を追加したくないとき。

public static class EnumerableExtension
{
    /// <summary>
    /// Causes immediate evaluation of the linq but only if required.
    /// As it returns a readonly ICollection, is better than using ToList or ToArray
    /// when you do not want to use the indexing properties of an IList, or add to the collection.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="enumerable"></param>
    /// <returns>Readonly collection</returns>
    public static ICollection<T> Evaluate<T>(this IEnumerable<T> enumerable)
    {
        //if it's already a readonly collection, use it
        var collection = enumerable as ICollection<T>;
        if ((collection != null) && collection.IsReadOnly)
        {
            return collection;
        }
        //or make a new collection
        return enumerable.ToList().AsReadOnly();
    }
}

単体テスト:

[TestClass]
public sealed class EvaluateLinqTests
{
    [TestMethod]
    public void EvalTest()
    {
        var list = new List<int> {1, 2, 3};
        var linqResult = list.Select(i => i);
        var linqResultEvaluated = list.Select(i => i).Evaluate();
        list.Clear();
        Assert.AreEqual(0, linqResult.Count());
        //even though we have cleared the underlying list, the evaluated list does not change
        Assert.AreEqual(3, linqResultEvaluated.Count());
    }

    [TestMethod]
    public void DoesNotSaveCreatingListWhenHasListTest()
    {
        var list = new List<int> {1, 2, 3};
        var linqResultEvaluated = list.Evaluate();
        //list is not readonly, so we expect a new list
        Assert.AreNotSame(list, linqResultEvaluated);
    }

    [TestMethod]
    public void SavesCreatingListWhenHasReadonlyListTest()
    {
        var list = new List<int> {1, 2, 3}.AsReadOnly();
        var linqResultEvaluated = list.Evaluate();
        //list is readonly, so we don't expect a new list
        Assert.AreSame(list, linqResultEvaluated);
    }

    [TestMethod]
    public void SavesCreatingListWhenHasArrayTest()
    {
        var list = new[] {1, 2, 3};
        var linqResultEvaluated = list.Evaluate();
        //arrays are readonly (wrt ICollection<T> interface), so we don't expect a new object
        Assert.AreSame(list, linqResultEvaluated);
    }

    [TestMethod]
    [ExpectedException(typeof (NotSupportedException))]
    public void CantAddToResultTest()
    {
        var list = new List<int> {1, 2, 3};
        var linqResultEvaluated = list.Evaluate();
        Assert.AreNotSame(list, linqResultEvaluated);
        linqResultEvaluated.Add(4);
    }

    [TestMethod]
    [ExpectedException(typeof (NotSupportedException))]
    public void CantRemoveFromResultTest()
    {
        var list = new List<int> {1, 2, 3};
        var linqResultEvaluated = list.Evaluate();
        Assert.AreNotSame(list, linqResultEvaluated);
        linqResultEvaluated.Remove(1);
    }
}

読み取り専用のコレクションコントラクトでは、オブジェクトのユーザーがオブジェクトを変更できないことを規定しているだけですが、変更可能なインターフェイスを提供するオブジェクトへの参照を保持している場合、所有者は変更できることに注意してください。基本となる構造が決して変更されないことを保証するインターフェースについては、不変コレクションをご覧ください。不変コレクション、読み取り専用コレクション、またはプレーンな読み取り/書き込みコレクションの方が良いか悪いかについては、比較のための参照ポイントが必要です。最終的な答えはありません(それ以外の場合は選択する必要はありません)。
2014年

@tne Note ToReadはAsReadOnlyの前に行うため、基になるミュータブルへの参照はありません。
ウェストン2014年

あなたは完全に正しいです、そしてそれは不変のコレクションがBCLに来る前に物事を行うためのおそらく最良の方法でした(私は最初のベータがあなたの答えの1か月後に出たと思います)。
2014年

不変のコレクションはスレッドセーフのために存在し、スレッドは変更されないと想定できます。変更された場合は、リーダーと競合して使用中に変更するのではなく、新しいバージョンが作成されます。この方法では、誰もロックを取得する必要はありません。
doug65536

4

ToListAsync<T>() 推奨されます。

Entity Framework 6では、両方のメソッドが最終的に同じ内部メソッドをToArrayAsync<T>()呼び出しますlist.ToArray()が、最後に呼び出します。

T[] array = new T[_size];
Array.Copy(_items, 0, array, 0, _size);
return array;

そのToArrayAsync<T>()ため、いくつかのオーバーヘッドがあるため、ToListAsync<T>()優先されます。


1
それが実際に私が探していた答えであり、EFはそれをどのように行っていますか。EF Coreでそれがどのように機能するのか知りたいです。
Shimmy Weitzhandler 2018

3

古い質問ですが、常に新しい質問者です。

System.Linq.Enumerableのソースによると、ToList単にを返すnew List(source)一方で、をToArray使用してnew Buffer<T>(source).ToArray()を返しますT[]

メモリ割り当てについて:

IEnumerable<T>唯一のオブジェクトで実行している間は、ToArrayメモリを1回以上割り当てますToList。ただし、GCは必要に応じてガベージコレクションを実行するため、ほとんどの場合、そのことを気にする必要はありません。

ランタイム効率について:

この質問をしている人は、あなたのマシンで次のコードを実行することができ、あなたはあなたの答えを得るでしょう。

class PersonC
{
    public Guid uuid;
    public string name;
    public int age;
    public bool sex;
    public DateTime BirthDay;
    public double weight;
}

struct PersonS
{
    public Guid uuid;
    public string name;
    public int age;
    public bool sex;
    public DateTime BirthDay;
    public double weight;
}

class PersonT<T> : IEnumerable<T>
{
    private List<T> items;
    public PersonT(IEnumerable<T> init)
    {
        items = new List<T>(init);
    }

    public IEnumerator<T> GetEnumerator() => items.GetEnumerator();
    IEnumerator IEnumerable.GetEnumerator() => items.GetEnumerator();
}

private IEnumerable<PersonC> C(int count)
{
    for (var i = 0; i < count; ++i)
    {
        var guid = Guid.NewGuid();
        var guidBytes = guid.ToByteArray(); //16 bytes
        yield return new PersonC
        {
            uuid = guid,
            name = guid.ToString(),
            age = guidBytes[0] ^ guidBytes[7],
            sex = guidBytes[14] % 2 == 0,
            BirthDay = DateTime.Now.AddDays(-guidBytes[11] * 18),
            weight = guidBytes[12] * 100
        };
    }
}

private IEnumerable<PersonS> S(int count)
{
    for (var i = 0; i < count; ++i)
    {
        var guid = Guid.NewGuid();
        var guidBytes = guid.ToByteArray(); //16 bytes
        yield return new PersonS
        {
            uuid = guid,
            name = guid.ToString(),
            age = guidBytes[0] ^ guidBytes[7],
            sex = guidBytes[14] % 2 == 0,
            BirthDay = DateTime.Now.AddDays(-guidBytes[11] * 18),
            weight = guidBytes[12] * 100
        };
    }
}

private void MakeLog(string test, List<long> log) =>
    Console.WriteLine("{0} {1} ms -> [{2}]",
        test,
        log.Average(),
        string.Join(", ", log)
    );

private void Test1(int times, int count)
{
    var test = Enumerable.Range(1, times).ToArray();

    MakeLog("C.ToList", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = C(count).ToList();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());

    MakeLog("C.ToArray", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = C(count).ToArray();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());

    MakeLog("S.ToList", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = S(count).ToList();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());

    MakeLog("S.ToArray", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = S(count).ToArray();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());
}

private void Test2(int times, int count)
{
    var test = Enumerable.Range(1, times).ToArray();

    var dataC1 = new PersonT<PersonC>(C(count));
    var dataS1 = new PersonT<PersonS>(S(count));

    MakeLog("C1.ToList", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = dataC1.ToList();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());

    MakeLog("C1.ToArray", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = dataC1.ToArray();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());

    MakeLog("S1.ToList", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = dataS1.ToList();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());

    MakeLog("S1.ToArray", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = dataS1.ToArray();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());
}

private void Test3(int times, int count)
{
    var test = Enumerable.Range(1, times).ToArray();

    var dataC2 = (ICollection<PersonC>) new List<PersonC>(C(count));
    var dataS2 = (ICollection<PersonS>) new List<PersonS>(S(count));

    MakeLog("C2.ToList", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = dataC2.ToList();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());

    MakeLog("C2.ToArray", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = dataC2.ToArray();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());

    MakeLog("S2.ToList", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = dataS2.ToList();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());

    MakeLog("S2.ToArray", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = dataS2.ToArray();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());
}

private void TestMain()
{
    const int times = 100;
    const int count = 1_000_000 + 1;
    Test1(times, count);
    Test2(times, count);
    Test3(times, count);
}

私のマシンでこれらの結果を得ました:

グループ1:

C.ToList 761.79 ms -> [775, 755, 759, 759, 756, 759, 765, 750, 757, 762, 759, 754, 757, 753, 763, 753, 759, 756, 768, 754, 763, 757, 757, 777, 780, 758, 754, 758, 762, 754, 758, 757, 763, 758, 760, 754, 761, 755, 764, 847, 952, 755, 747, 763, 760, 758, 754, 763, 761, 758, 750, 764, 757, 763, 762, 756, 753, 759, 759, 757, 758, 779, 765, 760, 760, 756, 760, 756, 755, 764, 759, 753, 757, 760, 752, 764, 758, 760, 758, 760, 755, 761, 751, 753, 761, 762, 761, 758, 759, 752, 765, 756, 760, 755, 757, 753, 760, 751, 755, 779]
C.ToArray 782.56 ms -> [783, 774, 771, 771, 773, 774, 775, 775, 772, 770, 771, 774, 771, 1023, 975, 772, 767, 776, 771, 779, 772, 779, 775, 771, 775, 773, 775, 771, 765, 774, 770, 781, 772, 771, 781, 762, 817, 770, 775, 779, 769, 774, 763, 775, 777, 769, 777, 772, 775, 778, 775, 771, 770, 774, 772, 769, 772, 769, 774, 775, 768, 775, 769, 774, 771, 776, 774, 773, 778, 769, 778, 767, 770, 787, 783, 779, 771, 768, 805, 780, 779, 767, 773, 771, 773, 785, 1044, 853, 775, 774, 775, 771, 770, 769, 770, 776, 770, 780, 821, 770]
S.ToList 704.2 ms -> [687, 702, 709, 691, 694, 710, 696, 698, 700, 694, 701, 719, 706, 694, 702, 699, 699, 703, 704, 701, 703, 705, 697, 707, 691, 697, 707, 692, 721, 698, 695, 700, 704, 700, 701, 710, 700, 705, 697, 711, 694, 700, 695, 698, 701, 692, 696, 702, 690, 699, 708, 700, 703, 714, 701, 697, 700, 699, 694, 701, 697, 696, 699, 694, 709, 1068, 690, 706, 699, 699, 695, 708, 695, 704, 704, 700, 695, 704, 695, 696, 702, 700, 710, 708, 693, 697, 702, 694, 700, 706, 699, 695, 706, 714, 704, 700, 695, 697, 707, 704]
S.ToArray 742.5 ms -> [742, 743, 733, 745, 741, 724, 738, 745, 728, 732, 740, 727, 739, 740, 726, 744, 758, 732, 744, 745, 730, 739, 738, 723, 745, 757, 729, 741, 736, 724, 744, 756, 739, 766, 737, 725, 741, 742, 736, 748, 742, 721, 746, 1043, 806, 747, 731, 727, 742, 742, 726, 738, 746, 727, 739, 743, 730, 744, 753, 741, 739, 746, 728, 740, 744, 734, 734, 738, 731, 747, 736, 731, 765, 735, 726, 740, 743, 730, 746, 742, 725, 731, 757, 734, 738, 741, 732, 747, 744, 721, 742, 741, 727, 745, 740, 730, 747, 760, 737, 740]

C1.ToList 32.34 ms -> [35, 31, 31, 31, 32, 31, 31, 31, 31, 31, 31, 31, 31, 31, 33, 32, 31, 31, 31, 31, 30, 32, 31, 31, 31, 31, 32, 30, 31, 31, 31, 30, 32, 31, 31, 31, 36, 31, 31, 31, 32, 30, 31, 32, 31, 31, 31, 31, 31, 32, 31, 31, 31, 31, 33, 32, 31, 32, 31, 31, 33, 31, 31, 31, 31, 31, 32, 31, 32, 31, 34, 38, 68, 42, 79, 33, 31, 31, 31, 31, 31, 30, 30, 30, 30, 31, 31, 31, 31, 32, 31, 32, 31, 31, 31, 32, 33, 33, 31, 31]
C1.ToArray 56.32 ms -> [57, 56, 59, 54, 54, 55, 56, 57, 54, 54, 55, 55, 57, 56, 59, 57, 56, 58, 56, 56, 54, 56, 57, 55, 55, 55, 57, 58, 57, 58, 55, 55, 56, 55, 57, 56, 56, 59, 56, 56, 56, 56, 58, 56, 57, 56, 56, 57, 56, 55, 56, 56, 56, 59, 56, 56, 56, 55, 55, 54, 55, 54, 57, 56, 56, 56, 55, 55, 56, 56, 56, 59, 56, 56, 57, 56, 57, 56, 56, 56, 56, 62, 55, 56, 56, 56, 69, 57, 58, 56, 57, 58, 56, 57, 56, 56, 56, 56, 56, 56]
S1.ToList 88.69 ms -> [96, 90, 90, 89, 91, 88, 89, 90, 96, 89, 89, 89, 90, 90, 90, 89, 90, 90, 89, 90, 89, 91, 89, 91, 89, 91, 89, 90, 90, 89, 87, 88, 87, 88, 87, 87, 87, 87, 88, 88, 87, 87, 89, 87, 87, 87, 91, 88, 87, 86, 89, 87, 90, 89, 89, 90, 89, 87, 87, 87, 86, 87, 88, 90, 88, 87, 87, 92, 87, 87, 88, 88, 88, 86, 86, 87, 88, 87, 87, 87, 89, 87, 89, 87, 90, 89, 89, 89, 91, 89, 90, 89, 90, 88, 90, 90, 90, 88, 89, 89]
S1.ToArray 143.26 ms -> [130, 129, 130, 131, 133, 130, 131, 130, 135, 137, 130, 136, 132, 131, 130, 131, 132, 130, 132, 136, 130, 131, 157, 153, 194, 364, 176, 189, 203, 194, 189, 192, 183, 140, 142, 147, 145, 134, 159, 158, 142, 167, 130, 143, 145, 144, 160, 154, 156, 153, 153, 164, 142, 145, 137, 134, 145, 143, 142, 135, 133, 133, 135, 134, 134, 139, 139, 133, 134, 141, 133, 132, 133, 132, 133, 131, 135, 132, 133, 132, 128, 128, 130, 132, 129, 129, 129, 129, 129, 128, 134, 129, 129, 129, 129, 128, 128, 137, 130, 131]

C2.ToList 3.25 ms -> [5, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 3, 3, 4, 4, 3, 3, 3, 4, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 4, 3, 3, 3, 3, 3, 4, 3, 4, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 3, 3, 4, 3, 3, 4, 3, 3, 3, 4, 3, 3, 3, 3, 3]
C2.ToArray 3.37 ms -> [4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 4, 9, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 4, 3, 3, 4, 4, 3, 3, 3, 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 4, 4, 3, 4, 4, 3, 3, 4, 3, 3, 4, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 4, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 3, 4, 3, 3, 3]
S2.ToList 37.72 ms -> [38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 40, 38, 38, 39, 39, 38, 38, 38, 38, 37, 37, 37, 37, 39, 37, 37, 39, 38, 37, 37, 37, 37, 39, 38, 37, 37, 38, 37, 38, 37, 37, 38, 37, 37, 37, 38, 37, 37, 36, 37, 38, 37, 39, 37, 39, 38, 37, 38, 38, 38, 38, 38, 38, 37, 38, 38, 38, 38, 38, 37, 38, 37, 37, 38, 37, 37, 39, 41, 37, 38, 38, 37, 37, 37, 37, 38, 37, 37, 37, 40, 37, 37, 37, 37, 39, 38]
S2.ToArray 38.86 ms -> [39, 37, 39, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 38, 38, 38, 39, 37, 38, 38, 38, 38, 38, 37, 37, 38, 37, 37, 38, 38, 40, 38, 38, 38, 38, 38, 39, 38, 38, 39, 38, 38, 39, 38, 38, 40, 38, 39, 38, 38, 39, 38, 38, 38, 38, 38, 39, 38, 38, 38, 39, 39, 37, 38, 38, 39, 71, 78, 37, 37, 37, 39, 38, 38, 39, 38, 38, 38, 38, 38, 39, 38, 38, 38, 39, 38, 38, 38]

グループ2:

C.ToList 756.81 ms
C.ToArray 774.21 ms
S.ToList 709.7 ms
S.ToArray 753.51 ms

C1.ToList 32.06 ms
C1.ToArray 56.58 ms
S1.ToList 89.43 ms
S1.ToArray 132.85 ms

C2.ToList 3.45 ms
C2.ToArray 3.36 ms
S2.ToList 41.43 ms
S2.ToArray 40.84 ms

グループ3:

C.ToList 756.64 ms
C.ToArray 771.56 ms
S.ToList 705.42 ms
S.ToArray 749.59 ms

C1.ToList 31.45 ms
C1.ToArray 57.03 ms
S1.ToList 91.26 ms
S1.ToArray 129.77 ms

C2.ToList 3.26 ms
C2.ToArray 3.29 ms
S2.ToList 41.57 ms
S2.ToArray 40.69 ms

グループ4:

C.ToList 729.65 ms -> [749, 730, 721, 719, 723, 743, 721, 724, 727, 722, 716, 725, 723, 726, 718, 722, 731, 722, 723, 725, 723, 722, 728, 726, 728, 718, 726, 1088, 788, 737, 729, 710, 730, 728, 717, 723, 728, 721, 722, 728, 722, 736, 723, 729, 732, 724, 726, 727, 728, 728, 726, 726, 725, 727, 725, 728, 728, 718, 724, 725, 726, 724, 726, 729, 727, 722, 722, 725, 725, 728, 724, 727, 738, 717, 726, 723, 725, 725, 727, 724, 720, 726, 726, 723, 727, 730, 723, 721, 725, 727, 727, 733, 720, 722, 722, 725, 722, 725, 728, 726]
C.ToArray 788.36 ms -> [748, 740, 742, 797, 1090, 774, 781, 787, 784, 786, 786, 782, 781, 781, 784, 783, 783, 781, 783, 787, 783, 784, 775, 789, 784, 785, 778, 774, 781, 783, 786, 781, 780, 788, 778, 785, 777, 781, 786, 782, 781, 787, 782, 787, 784, 773, 783, 782, 781, 777, 783, 781, 785, 788, 777, 776, 784, 784, 783, 789, 778, 781, 791, 768, 779, 783, 781, 787, 786, 781, 784, 781, 785, 781, 780, 809, 1155, 780, 790, 789, 783, 776, 785, 783, 786, 787, 782, 782, 787, 777, 779, 784, 783, 776, 786, 775, 782, 779, 784, 784]
S.ToList 705.54 ms -> [690, 705, 709, 708, 702, 707, 703, 696, 703, 702, 700, 703, 700, 707, 705, 699, 697, 703, 695, 698, 707, 697, 711, 710, 699, 700, 708, 707, 693, 710, 704, 691, 702, 700, 703, 700, 705, 700, 703, 695, 709, 705, 698, 699, 709, 700, 699, 704, 691, 705, 703, 700, 708, 1048, 710, 706, 706, 692, 702, 705, 695, 701, 710, 697, 698, 706, 705, 707, 707, 695, 698, 704, 698, 699, 705, 698, 703, 702, 701, 697, 702, 702, 704, 703, 699, 707, 703, 705, 701, 717, 698, 695, 713, 696, 708, 705, 697, 699, 700, 698]
S.ToArray 745.01 ms -> [751, 743, 727, 734, 736, 745, 739, 750, 739, 750, 758, 739, 744, 738, 730, 744, 745, 739, 744, 750, 733, 735, 743, 731, 749, 748, 727, 746, 749, 731, 737, 803, 1059, 756, 769, 748, 740, 745, 741, 746, 749, 732, 741, 742, 732, 744, 746, 737, 742, 739, 733, 744, 741, 729, 746, 760, 725, 741, 764, 739, 750, 751, 727, 745, 738, 727, 735, 741, 720, 736, 740, 733, 741, 746, 731, 749, 756, 740, 738, 736, 732, 741, 741, 733, 741, 744, 736, 742, 742, 735, 743, 746, 729, 748, 765, 743, 734, 742, 728, 749]

C1.ToList 32.27 ms -> [36, 31, 31, 32, 31, 32, 31, 30, 32, 30, 30, 30, 34, 32, 31, 31, 31, 31, 31, 31, 31, 32, 38, 51, 68, 57, 35, 30, 31, 31, 30, 30, 33, 30, 31, 34, 31, 34, 32, 31, 31, 31, 31, 32, 30, 30, 31, 30, 31, 31, 32, 31, 31, 31, 32, 31, 31, 31, 32, 31, 33, 31, 31, 32, 30, 30, 30, 30, 30, 33, 30, 33, 32, 31, 30, 31, 31, 32, 32, 31, 35, 31, 34, 31, 31, 32, 31, 31, 32, 31, 32, 31, 31, 35, 31, 31, 31, 31, 31, 32]
C1.ToArray 56.72 ms -> [58, 56, 57, 57, 59, 58, 58, 57, 56, 59, 57, 55, 55, 54, 56, 55, 56, 56, 57, 59, 56, 55, 58, 56, 55, 55, 55, 55, 58, 58, 55, 57, 57, 56, 57, 57, 57, 57, 59, 59, 56, 57, 56, 57, 57, 56, 57, 59, 58, 56, 57, 57, 57, 58, 56, 56, 59, 56, 59, 57, 57, 57, 57, 59, 57, 56, 57, 56, 58, 56, 57, 56, 57, 59, 55, 58, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 56, 56, 57, 56, 56, 57, 58, 57, 57, 57, 57, 57]
S1.ToList 90.72 ms -> [95, 90, 90, 89, 89, 89, 91, 89, 89, 87, 91, 89, 89, 89, 91, 89, 89, 89, 90, 89, 89, 90, 88, 89, 88, 90, 89, 90, 89, 89, 90, 90, 89, 89, 90, 91, 89, 91, 89, 90, 89, 89, 90, 91, 89, 89, 89, 89, 89, 89, 90, 89, 89, 89, 90, 89, 90, 89, 91, 89, 90, 89, 90, 89, 90, 89, 96, 89, 90, 89, 89, 89, 89, 89, 90, 89, 89, 89, 90, 87, 89, 90, 90, 91, 89, 91, 89, 89, 90, 91, 90, 89, 93, 144, 149, 90, 90, 89, 89, 89]
S1.ToArray 131.4 ms -> [130, 128, 127, 134, 129, 129, 130, 136, 131, 130, 132, 132, 133, 131, 132, 131, 133, 132, 130, 131, 132, 131, 130, 133, 133, 130, 130, 131, 131, 131, 132, 134, 131, 131, 132, 131, 132, 131, 134, 131, 131, 130, 131, 131, 130, 132, 129, 131, 131, 131, 132, 131, 133, 134, 131, 131, 132, 132, 131, 133, 131, 131, 130, 133, 131, 130, 134, 132, 131, 132, 132, 131, 131, 134, 131, 131, 132, 132, 131, 130, 138, 130, 130, 131, 132, 132, 130, 134, 131, 131, 132, 131, 130, 132, 133, 131, 131, 131, 130, 131]

C2.ToList 3.21 ms -> [4, 3, 3, 3, 4, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 4, 3, 4, 3, 3, 3, 3, 3, 4, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 4, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 3, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 3, 3, 3]
C2.ToArray 3.22 ms -> [4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 3, 3, 4, 3, 4, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 4, 3, 4, 3, 3, 3, 3, 3, 4, 3, 3, 3, 4, 3, 4, 3, 3, 3, 3, 4]
S2.ToList 41.46 ms -> [42, 40, 41, 40, 42, 40, 40, 40, 40, 40, 40, 40, 40, 41, 40, 40, 41, 40, 40, 40, 39, 41, 41, 39, 40, 40, 43, 40, 39, 40, 40, 40, 40, 40, 40, 41, 40, 40, 40, 43, 40, 43, 75, 76, 47, 39, 40, 40, 40, 40, 42, 40, 41, 40, 40, 40, 44, 41, 40, 42, 42, 40, 41, 41, 41, 41, 41, 40, 41, 41, 41, 41, 42, 41, 40, 41, 41, 42, 42, 41, 40, 41, 41, 41, 41, 41, 40, 42, 40, 42, 41, 41, 41, 43, 41, 41, 41, 41, 42, 41]
S2.ToArray 41.14 ms -> [42, 41, 41, 40, 40, 40, 40, 41, 41, 42, 41, 42, 41, 41, 41, 42, 41, 41, 42, 41, 41, 41, 41, 41, 42, 40, 41, 40, 42, 40, 42, 41, 40, 42, 41, 41, 43, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 41, 41, 41, 40, 42, 41, 41, 41, 41, 41, 40, 41, 41, 42, 41, 41, 41, 42, 41, 41, 41, 41, 41, 41, 42, 42, 42, 41, 45, 46, 41, 40, 41, 41, 42, 41, 41, 41, 41, 41, 41, 40, 41, 43, 40, 40, 40, 40, 43, 41]

グループ5:

C.ToList 757.06 ms -> [770, 752, 752, 751, 778, 763, 761, 763, 747, 758, 748, 747, 754, 749, 752, 753, 756, 762, 750, 753, 756, 749, 755, 757, 755, 756, 755, 744, 753, 758, 747, 751, 759, 751, 761, 755, 746, 752, 752, 749, 746, 752, 753, 755, 752, 755, 754, 754, 966, 937, 749, 759, 748, 747, 754, 749, 755, 750, 746, 754, 757, 752, 753, 745, 758, 755, 761, 753, 751, 755, 755, 752, 746, 756, 755, 746, 742, 751, 751, 749, 752, 751, 756, 756, 755, 742, 749, 754, 749, 756, 753, 751, 754, 752, 751, 754, 753, 749, 755, 756]
C.ToArray 772.8 ms -> [766, 772, 755, 763, 758, 767, 763, 762, 761, 768, 769, 763, 770, 757, 765, 760, 766, 759, 764, 761, 760, 777, 1102, 881, 759, 765, 758, 762, 772, 761, 758, 757, 765, 769, 769, 761, 762, 762, 763, 760, 770, 764, 760, 768, 758, 766, 763, 770, 769, 761, 764, 761, 761, 767, 761, 762, 764, 757, 765, 766, 767, 771, 753, 762, 769, 768, 759, 764, 764, 760, 763, 763, 763, 763, 763, 767, 761, 771, 760, 765, 760, 758, 768, 770, 751, 771, 767, 771, 765, 763, 760, 765, 765, 769, 767, 767, 1193, 774, 767, 764]
S.ToList 704.73 ms -> [682, 708, 705, 699, 705, 704, 695, 703, 702, 699, 701, 708, 699, 702, 703, 701, 701, 699, 701, 707, 707, 700, 701, 705, 700, 697, 706, 702, 701, 706, 699, 692, 702, 697, 707, 704, 697, 698, 699, 699, 702, 703, 698, 697, 702, 703, 702, 704, 694, 697, 707, 695, 711, 710, 700, 693, 703, 699, 699, 706, 698, 701, 703, 704, 698, 706, 700, 704, 701, 699, 702, 705, 694, 698, 709, 736, 1053, 704, 694, 700, 698, 696, 701, 700, 700, 706, 706, 692, 698, 707, 703, 695, 703, 699, 694, 708, 695, 694, 706, 695]
S.ToArray 744.17 ms -> [746, 740, 725, 740, 739, 731, 746, 760, 735, 738, 740, 734, 744, 748, 737, 744, 745, 727, 736, 738, 728, 743, 745, 735, 748, 760, 739, 748, 762, 742, 741, 747, 733, 746, 758, 742, 742, 741, 724, 744, 747, 727, 740, 740, 729, 742, 757, 741, 740, 742, 726, 739, 746, 1133, 749, 737, 730, 740, 747, 733, 747, 752, 731, 747, 742, 730, 741, 749, 731, 749, 743, 730, 747, 742, 731, 737, 745, 734, 739, 735, 727, 743, 752, 731, 744, 742, 729, 740, 746, 731, 739, 746, 733, 745, 743, 733, 739, 742, 727, 737]

C1.ToList 31.71 ms -> [35, 32, 32, 30, 31, 33, 31, 32, 32, 31, 31, 32, 32, 33, 32, 31, 31, 32, 31, 32, 32, 32, 31, 32, 33, 32, 31, 31, 31, 32, 31, 34, 31, 31, 32, 33, 32, 32, 31, 32, 34, 32, 31, 32, 33, 31, 32, 32, 31, 32, 32, 32, 32, 32, 32, 31, 31, 32, 31, 33, 30, 31, 32, 30, 30, 33, 32, 32, 34, 31, 31, 31, 31, 32, 31, 31, 31, 31, 32, 31, 31, 33, 31, 32, 32, 32, 33, 32, 31, 31, 31, 31, 31, 32, 32, 33, 32, 31, 31, 32]
C1.ToArray 59.53 ms -> [63, 57, 58, 58, 57, 59, 59, 57, 60, 131, 127, 67, 58, 56, 59, 56, 57, 58, 58, 58, 57, 59, 60, 57, 57, 59, 60, 57, 57, 57, 58, 58, 58, 58, 57, 57, 61, 57, 58, 57, 57, 57, 57, 57, 58, 58, 58, 58, 57, 58, 59, 57, 58, 57, 57, 59, 58, 58, 59, 57, 59, 57, 56, 56, 59, 56, 56, 59, 57, 58, 58, 58, 57, 58, 59, 59, 58, 57, 58, 62, 65, 57, 57, 57, 58, 60, 59, 58, 59, 57, 58, 57, 58, 59, 58, 58, 58, 59, 60, 58]
S1.ToList 82.78 ms -> [87, 82, 83, 83, 82, 82, 83, 84, 82, 83, 84, 84, 84, 82, 82, 84, 82, 84, 83, 84, 82, 82, 82, 81, 83, 83, 83, 84, 84, 82, 82, 83, 83, 83, 82, 83, 85, 83, 82, 82, 84, 82, 82, 83, 83, 83, 82, 82, 82, 83, 82, 83, 82, 84, 82, 83, 82, 83, 82, 82, 82, 84, 82, 83, 82, 82, 86, 83, 83, 82, 83, 83, 83, 82, 84, 82, 83, 81, 82, 82, 82, 82, 83, 83, 83, 82, 83, 84, 83, 82, 83, 83, 83, 82, 83, 84, 82, 82, 83, 83]
S1.ToArray 122.3 ms -> [122, 119, 119, 120, 119, 120, 120, 121, 119, 119, 122, 120, 120, 120, 122, 120, 123, 120, 120, 120, 121, 123, 120, 120, 120, 121, 120, 121, 122, 120, 123, 119, 121, 118, 121, 120, 120, 120, 119, 124, 119, 121, 119, 120, 120, 120, 120, 120, 122, 121, 123, 230, 203, 123, 119, 119, 122, 119, 120, 120, 120, 122, 120, 121, 120, 121, 120, 121, 120, 121, 120, 120, 120, 121, 122, 121, 123, 119, 119, 119, 119, 121, 120, 120, 120, 122, 121, 122, 119, 120, 120, 121, 121, 120, 121, 120, 121, 118, 118, 118]

C2.ToList 3.43 ms -> [5, 3, 4, 4, 4, 3, 4, 4, 4, 4, 4, 3, 3, 3, 4, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 4, 3, 3, 3, 3, 4, 3, 3, 3, 4, 3, 4, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 6, 4, 4, 3, 3, 4, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 4, 3, 4, 4, 4, 3, 4, 4, 3, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 4, 3, 3, 3, 3]
C2.ToArray 3.48 ms -> [3, 3, 3, 3, 4, 4, 3, 4, 4, 4, 3, 4, 3, 3, 4, 3, 3, 4, 3, 4, 3, 3, 3, 4, 3, 3, 3, 4, 3, 3, 3, 3, 4, 3, 4, 3, 3, 4, 3, 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 4, 3, 3, 4, 3, 4, 4, 3, 4, 4, 4, 4, 4, 3, 3, 3, 4, 4, 3, 4, 4, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 3]
S2.ToList 41.47 ms -> [41, 41, 49, 67, 82, 41, 41, 40, 40, 40, 40, 40, 41, 40, 40, 40, 40, 40, 41, 40, 42, 42, 40, 40, 41, 41, 41, 40, 41, 40, 41, 40, 41, 40, 42, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 42, 41, 41, 41, 42, 40, 41, 40, 40, 40, 42, 40, 41, 42, 41, 42, 41, 42, 40, 41, 41, 41, 41, 41, 41, 41, 41, 40, 41, 40, 41, 41, 41, 40, 41, 41, 40, 40, 41, 41, 41, 41, 41, 43, 40, 40, 41, 42, 41]
S2.ToArray 40.62 ms -> [42, 41, 44, 40, 40, 40, 40, 41, 41, 40, 41, 41, 41, 40, 41, 41, 40, 41, 41, 40, 41, 40, 40, 41, 42, 41, 41, 41, 40, 40, 40, 40, 40, 41, 41, 42, 40, 41, 41, 41, 41, 41, 40, 42, 40, 40, 41, 41, 41, 40, 41, 40, 40, 40, 40, 40, 41, 40, 40, 41, 40, 40, 40, 40, 41, 40, 41, 41, 41, 40, 41, 41, 40, 41, 40, 41, 42, 40, 41, 41, 42, 41, 41, 40, 41, 40, 41, 40, 41, 41, 40, 40, 40, 41, 41, 40, 40, 40, 40, 40]

Stackoverflowは回答の文字数に制限があるため、Group2とGroup3のサンプルリストは省略されています。

あなたが見ることができるように、それは実際に使用することが重要ではないのですToListか、ToArryほとんどの場合インチ

ランタイム計算の処理中 IEnumerable<T>負荷が計算によってもたらされた場合、オブジェクトをメモリ割当より重くのコピー操作ToListToArray、視差は軽微である(C.ToList vs C.ToArrayそしてS.ToList vs S.ToArray)。

違いは、実行時に計算されIEnumerable<T>ないオブジェクトのみ(C1.ToList vs C1.ToArrayおよびS1.ToList vs S1.ToArray)でのみ確認できます。ただし、100万個の小さなオブジェクトでは、絶対差(<60ms)は許容されますIEnumerable<T>。実際には、違いがの実装によって決定されるEnumerator<T>IEnumerable<T>。したがって、プログラムが本当にこれに非常に敏感な場合は、、プロファイル、プロファイル、プロファイルあります。やっとボトルネックがToListorにあるのToArrayではなく、列挙子の詳細に気付くでしょう。

そして、結果C2.ToList vs C2.ToArrayS2.ToList vs S2.ToArray、あなたが本当に気にする必要はありませんショーToListToArray非実行時に計算上のICollection<T>オブジェクト。

もちろん、これは私のマシンでの結果にすぎません。異なるマシンでのこれらの操作の実際の時間は同じではありません。上記のコードを使用してマシンで確認できます。

選択する必要がある唯一の理由は、@ Jeppe Stig Nielsenの回答で説明されているように、List<T>またはT[]に特定のニーズがあることです。


1

この結果を別のLinq-to-sqlなどで使用することに関心がある人

from q in context.MyTable
where myListOrArray.Contains(q.someID)
select q;

その場合、生成されるSQLは、myListOrArrayにリストと配列のどちらを使用しても同じです。このステートメントの前に列挙する理由さえ聞かれるかもしれませんが、IQueryableと(リストまたは配列)から生成されたSQLには違いがあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.