Perbedaan antara Select dan ConvertAll di C #

117

Saya punya beberapa Daftar:

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

Saya ingin menerapkan beberapa transformasi ke elemen daftar saya. Saya dapat melakukan ini dengan dua cara:

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

Apa perbedaan antara kedua cara ini?

AndreyAkinshin
sumber
16
Anda tidak perlu .ToList () setelah ConvertAll ().
Gleno
belum pernah mendengar tentang ConvertAll, mengetahui sesuatu yang baru hari ini
Amit Bisht

Jawaban:

117

Selectadalah metode ekstensi LINQ dan bekerja pada semua IEnumerable<T>objek sedangkan ConvertAlldiimplementasikan hanya oleh List<T>. The ConvertAllMetode ada sejak NET 2.0 sedangkan LINQ diperkenalkan dengan 3,5.

Anda harus memilih Selectalih ConvertAllkarena berfungsi untuk semua jenis daftar, tetapi pada dasarnya mereka melakukan hal yang sama.

Oliver Hanappi
sumber
7
Dan bagaimana dengan pertunjukannya? Jika saya memiliki Daftar, apakah lebih baik menggunakan ConvertAll atau Select?
Nicolas
@Nicolas: Total waktu eksekusi hampir sama, tetapi mereka melakukan pemrosesan secara berbeda sehingga cocok untuk situasi yang berbeda. Saya menambahkan beberapa tentang itu dalam jawaban saya.
Guffa
3
Anda tidak dapat membandingkan Selectdan ConvertAll. Yang pertama memilih setiap item secara berurutan dan Anda bebas melakukan apa pun yang Anda inginkan. Yang terakhir memiliki maksud yang jelas: ubah item ini menjadi sesuatu yang lain.
Tim Schmelter
1
Menariknya, kelas List <T> berisi beberapa metode yang hampir sama persis di LINQ. Ada -> Apa Saja, Temukan -> Pertama, Temukan Semua -> Dimana, FindLast -> Terakhir, TrueForAll -> Semua
Mikal Schacht Jensen
Perbedaan antara ConvertAll dan Select adalah ConvertAll akan mengalokasikan ukuran daftar sebelumnya. Untuk urutan yang besar, ini akan membuat perbedaan performa. Jadi, jika kinerja adalah tujuan Anda, gunakan ConvertAll. Jika performa bukan masalah, gunakan Select karena lebih idiomatis dalam bahasa dan beri tahu performa pembaca di masa mendatang bukan masalah.
Durdsoft
82

ConvertAllbukan sebuah ekstensi, ini adalah metode dalam kelas daftar. Anda tidak perlu memanggil ToListhasilnya karena sudah ada daftar:

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

Jadi, perbedaannya adalah bahwa ConvertAllmetode ini hanya dapat digunakan pada daftar, dan mengembalikan daftar. The SelectMetode dapat digunakan pada setiap koleksi yang mengimplementasikan dalam IEnumerable<T>antarmuka, dan mengembalikan sebuah IEnumerable<T>.

Selain itu, mereka melakukan pemrosesan secara berbeda, sehingga mereka memiliki kekuatan dalam situasi yang berbeda. The ConvertAllMetode berjalan melalui daftar dan membuat daftar baru dalam satu pergi, sedangkan Selectmetode menggunakan eksekusi malas dan hanya memproses item yang Anda butuhkan mereka. Jika Anda tidak membutuhkan semua item, Selectmetode ini lebih efisien. Di sisi lain, setelah ConvertAllmengembalikan daftar, Anda tidak perlu menyimpan daftar asli.

Guffa
sumber
Bisa dibilang, seseorang tidak pernah harus "menyimpan daftar asli": itu akan dilakukan sesuai kebutuhan oleh GC.
user2864740
8
@ user2864740: Ya, itu benar jika sumber hanya berupa daftar dalam memori. Jika dibaca dari misalnya sebuah file maka Anda harus membiarkan file tersebut tetap terbuka sampai Anda telah memproses hasilnya dari Select.
Guffa
19

Jawaban pertama bukanlah jawaban yang diterima. Saya mantan 2007 C # Microsoft MVP.

Berbeda dengan respons yang diterima, ConvertAlljauh lebih efisien daripada kombinasi Selectdan ToList().

Pertama-tama, ConvertAllini benar-benar lebih cepat dan menggunakan jumlah memori minimum untuk melakukannya. Sama seperti Array.ConvertAll vs Select dan ToArray. Ini akan jauh lebih jelas dengan larik panjang yang lebih besar atau banyak panggilan dalam satu loop.

1) ConvertAllmengetahui ukuran daftar akhir dan menghindari mengalokasikan kembali array dasar. ToList() akan terus mengubah ukuran larik beberapa kali.

2) ToListakan membuat IEnumerable<>panggilan antarmuka lebih lambat , sementara ConvertAllakan mengulang melalui array yang mendasarinya tanpa panggilan tambahan atau pemeriksaan jangkauan.

3) Pilih akan membuat IEnumerable<T>objek ekstra .

Wesner Moise
sumber
1

Saya tahu ini agak terlambat tetapi saya masih menambahkan karena ini bisa berguna bagi orang lain di masa depan.

Saat menggunakannya dalam ekspresi kueri EntityFramework, tidak disarankan untuk menggunakan ConvertAll () karena ini mengevaluasi ekspresi daripada membiarkannya sebagai ekspresi untuk digunakan di masa mendatang. Ini sangat menurunkan kinerja eksekusi kueri database karena harus membuat sejumlah panggilan sebelum mengevaluasi ekspresi akhir.

Navap
sumber
9
Tidak terlalu. Seperti yang ditunjukkan Guffa dalam jawaban ini , ConvertAll adalah metode aktifList<T> . Pada saat Anda memiliki daftarnya, Anda telah mengevaluasi ekspresi Anda. Tetapi Anda benar - jika Anda tidak ingin mengevaluasi semua, Selectlebih baik.
Wai Ha Lee