C#でのSelectとConvertAllの違い


117

私はいくつかのリストがあります:

List<int> list = new List<int> { 1, 2, 3, 4, 5 };

リストの要素に変換を適用したい。これは2つの方法で実行できます。

List<int> list1 = list.Select(x => 2 * x).ToList();
List<int> list2 = list.ConvertAll(x => 2 * x).ToList();

これら2つの方法の違いは何ですか?


16
ConvertAll()の後に.ToList()を実行する必要はありません。
グレノ2011

ConvertAllについて聞いたことがない、今日何か新しいことを知った
アミットビシュット

回答:


117

SelectはLINQ拡張メソッドであり、すべてのIEnumerable<T>オブジェクトに対して機能しますが、ConvertAllによってのみ実装されList<T>ます。このConvertAll方法は.NET 2.0以降に存在しますが、LINQは3.5で導入されました。

あなたは賛成すべきであるSelect以上ConvertAll、それはリストの任意の種類のために働くように、彼らは基本的に同じことを行います。


7
そして、パフォーマンスについてはどうですか?リストを持っている場合、ConvertAllまたはSelectを使用した方がパフォーマンスが向上しますか?
Nicolas

@Nicolas:合計実行時間はほぼ同じですが、処理が異なるため、異なる場所に適合します。私はそれについて私の答えにいくつか追加しました。
Guffa

3
あなたは比較することはできませんSelectConvertAll。前者はシーケンス内のすべてのアイテムを選択し、あなたはそれを使って何でも好きなことをすることができます。後者には明確な意図があります。このアイテムを別のアイテムに変換します。
Tim Schmelter 2016

1
興味深いことに、List <T>クラスには、LINQでほぼ完全に一致するいくつかのメソッドが含まれています。存在->すべて、検索->最初、FindAll->どこで、FindLast->最後、TrueForAll->すべて
Mikal Schacht Jensen

ConvertAllとSelectの違いは、ConvertAllは事前にリストのサイズを割り当てることです。シーケンスが大きい場合、これによりパフォーマンスに違いが生じます。したがって、パフォーマンスが目的の場合は、ConvertAllを使用します。パフォーマンスが問題ではない場合は、Selectを使用します。これは、言語でより慣用的であり、パフォーマンスが問題ではないことを将来の読者に伝えるためです。
Durdsoft

82

ConvertAll拡張機能ではなく、リストクラスのメソッドです。ToList結果はすでにリストであるため、結果を呼び出す必要はありません。

List<int> list2 = list.ConvertAll(x => 2 * x);

そのため、違いは、ConvertAllメソッドはリストでのみ使用でき、リストを返すことです。このSelectメソッドは、IEnumerable<T>インターフェースを実装する任意のコレクションで使用でき、を返しますIEnumerable<T>

また、処理方法が異なるため、状況に応じて長所があります。ConvertAllこの方法は、リストを実行し、一方で、一度に新たなリストを作成Selectする方法は、怠惰な実行を使用して、あなたがそれらを必要と項目だけを処理します。すべてのアイテムが必要ない場合Selectは、この方法の方が効率的です。一方、ConvertAllリストが返されたら、元のリストを保持する必要はありません。


間違いなく、「元のリストを保持する」必要は決してありません。GCによって必要に応じて行われます。
user2864740 2016年

8
@ user2864740:はい、ソースが厳密にメモリ内のリストである場合はそうです。たとえばファイルから読み取られた場合は、からの結果を処理するまでファイルを開いたままにする必要がありますSelect
Guffa 2016年

19

最初の答えは受け入れられるべきではありません。私は以前の2007 C#Microsoft MVPです。

受け入れられた応答とConvertAllは対照的に、Selectとの組み合わせよりもはるかに効率的ですToList()

まず、ConvertAll厳密に高速であり、そのために最小限のメモリを使用します。Array.ConvertAll vs SelectおよびToArrayと同じです。これは、より長い配列またはループ内の多くの呼び出しで、はるかに明白になります。

1)ConvertAll最終リストのサイズを認識し、基本配列の再割り当てを回避します。ToList()は、配列のサイズを何度も変更し続けます。

2)追加の呼び出しや範囲チェックを行わずに、基になる配列をループしながら、ToList遅いインターフェイスIEnumerable<>呼び出しを行いConvertAllます。

3)選択すると、追加のIEnumerable<T>オブジェクトが作成されます。


1

これは少し遅れていることはわかっていますが、将来的に他のユーザーに役立つ可能性があるため、まだ追加しています。

EntityFrameworkクエリ式で使用する場合、ConvertAll()を使用することはお勧めしません。将来の使用のために式として残すのではなく、式を評価するからです。これは、最終式を評価する前に多数の呼び出しを行わなければならないため、データベースクエリの実行パフォーマンスを大幅に低下させます。


9
結構です。Guffa がこの回答で指摘しているようにConvertAll はメソッドList<T>です。あなたは、時間によって持っているリストを、あなたはすでにあなたの式を評価したしました。しかし、あなたは正しい-すべてを評価したくない場合Selectは、それが望ましい。
Wai Ha Lee
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.