C # 'da Select ve ConvertAll arasındaki fark


117

Listem var:

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

Listemin unsurlarına bazı dönüşümler uygulamak istiyorum. Bunu iki şekilde yapabilirim:

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

Bu iki yol arasındaki fark nedir?


16
ConvertAll () sonrasında .ToList () yapmanıza gerek yoktur.
Gleno

ConvertAll duymadım, yeni bugün bir şey bilmek lazım
Amit Bisht

Yanıtlar:


117

Selectbir LINQ genişletme yöntemidir ve tüm IEnumerable<T>nesneler üzerinde çalışır, ancak ConvertAllyalnızca List<T>. ConvertAllLINQ 3.5 ile tanıtıldı ise yöntem, .NET 2.0 beri var.

Sen iyilik etmelidir Selectüzerinde ConvertAlllistenin her türlü çalışır gibi, ancak temelde aynı şeyi.


7
Peki ya performanslar? Listem varsa, ConvertAll veya Select'i kullanmak daha mı verimli?
Nicolas

@Nicolas: Toplam yürütme süresi aşağı yukarı aynıdır, ancak farklı durumlara uymaları için işlemi farklı şekilde yaparlar. Cevabıma bununla ilgili biraz ekledim.
Guffa

3
Kıyaslayamazsınız Selectve ConvertAll. İlki, sırayla her öğeyi seçer ve onunla istediğiniz her şeyi yapmakta özgürsünüz. İkincisinin açık bir niyeti var: Bu öğeyi başka bir şeye dönüştürmek.
Tim Schmelter

1
İlginç bir şekilde, List <T> sınıfı LINQ'da neredeyse tam eşleşmeleri olan birkaç yöntem içerir. Var -> Herhangi biri, Bul -> İlk, Tümünü Bul -> Nerede, Sonu Bul -> Son, TrueForAll -> Tümü
Mikal Schacht Jensen

ConvertAll ve Select arasındaki fark ConvertAll elden önce listenin boyutunu tahsis edecektir. Büyük bir sekans için bu bir performans farkı yaratacaktır. Bu nedenle, hedefiniz performanssa, ConvertAll kullanın. Performans sorun değilse, bu dilde daha deyimsel olduğundan ve gelecekteki okuyucuların performansının bir sorun olmadığını söylediğinden Seç'i kullanın.
Durdsoft

82

ConvertAllbir uzantı değil, liste sınıfındaki bir yöntem. ToListZaten bir liste olduğu için sonucu aramanıza gerek yok :

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

Dolayısıyla, fark, ConvertAllyöntemin yalnızca bir listede kullanılabilmesi ve bir liste döndürmesidir. SelectYöntem uygular herhangi bir toplama kullanılabilir IEnumerable<T>arayüzü ve bir döner IEnumerable<T>.

Ayrıca, işlemeyi farklı şekilde yaparlar, bu nedenle farklı durumlarda güçlü yönlerine sahiptirler. ConvertAllEderken yöntem listesi üzerinden çalışır ve tek seferde yeni bir liste oluşturur Selectyöntem tembel yürütme kullanır ve bunları ihtiyaç olarak sadece öğeleri işler. Tüm öğeye ihtiyacınız yoksa, Selectyöntem daha etkilidir. Öte yandan, ConvertAlllisteyi bir kez döndürdüğünüzde, orijinal listeyi saklamanıza gerek yoktur.


Muhtemelen, hiç kimse "orijinal listeyi saklamak" zorunda değildir: bu, GC'nin gerektirdiği şekilde yapılacaktır.
user2864740

8
@ user2864740: Evet, kaynak kesinlikle bellekte bir liste ise bu doğrudur. Örneğin bir dosyadan okunuyorsa, sonucunu .tml dosyasından işleyene kadar dosyayı açık tutmanız gerekir Select.
Guffa

19

İlk cevap kabul edilen cevap olmamalıdır. Ben eski bir 2007 C # Microsoft MVP'siyim.

Kabul edilen yanıt aksine, ConvertAllçok daha verimli kombinasyonu daha Selectve ToList().

Her şeyden önce, ConvertAllkesinlikle daha hızlıdır ve bunu yapmak için minimum miktarda bellek kullanır. Array.ConvertAll, Select ve ToArray ile aynıdır. Bu, daha büyük uzunlukta bir dizi veya bir döngü içindeki birçok çağrı ile çok daha belirgindir.

1) ConvertAllson listenin boyutunu bilir ve temel dizinin yeniden tahsis edilmesini önler. ToList() diziyi birden çok kez yeniden boyutlandırmaya devam eder.

2) ToListarayüz IEnumerable<>aramalarını yavaşlatırken , ConvertAllekstra aramalar veya aralık kontrolleri olmadan temeldeki dizide döngü yapacaktır.

3) Select fazladan bir IEnumerable<T>nesne oluşturacaktır .


1

Bunun biraz geç olduğunu biliyorum ama yine de ekledim çünkü bu gelecekte diğerleri için faydalı olabilir.

Bunu EntityFramework sorgu ifadesinde kullanırken, ileride kullanmak üzere ifade olarak bırakmak yerine değerlendirirken ConvertAll () kullanılması önerilmez. Bu, son ifadeyi değerlendirmeden önce çok sayıda çağrı yapması gerekeceğinden veritabanı sorgu yürütme performansını ciddi şekilde düşürür.


9
Pek değil. Guffa'nın bu cevapta işaret ettiği gibi ConvertAll , bir yöntemdirList<T> . Eğer zaman varsa liste, zaten ifade değerlendirilir ettik. Ama haklısın - hepsini değerlendirmek istemiyorsan Select, tercih edilir.
Wai Ha Lee
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.