Різниця між Select і ConvertAll у C #


117

У мене є список:

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

Я хочу застосувати деякі перетворення до елементів мого списку. Я можу це зробити двома способами:

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

Яка різниця між цими двома способами?


16
Не потрібно .ToList () після ConvertAll ().
Глено

ніколи не чув про ConvertAll, сьогодні дізнався щось нове
Аміт

Відповіді:


117

Selectє методом розширення LINQ і працює над усіма IEnumerable<T>об'єктами, тоді ConvertAllяк реалізується лише List<T>. ConvertAllМетод існує з .NET 2.0 , тоді як LINQ була введена з 3.5.

Ви повинні сприяти Selectбільш , ConvertAllяк це працює для будь-якого виду списку, але вони роблять те ж саме в принципі.


7
А як же виступи? Якщо у мене є список, чи ефективніше використовувати ConvertAll або Select?
Ніколя

@Nicolas: Загальний час виконання приблизно однаковий, але обробку вони виконують по-різному, щоб вони підходили для різних ситуацій. Я трохи додав про це у своїй відповіді.
Гуффа

3
Ви не можете порівняти Selectі ConvertAll. Перший вибирає кожен елемент у послідовності, і ви можете робити з ним все, що завгодно. Останній має чіткий намір: перетворити цей предмет на щось інше.
Тім Шмелтер

1
Цікаво, що клас List <T> містить декілька методів, які мають майже точні збіги в LINQ. Існує -> Будь-який, Знайдіть -> По-перше, FindAll -> Де, FindLast -> Останнє, TrueForAll -> Усі
Mikal Schacht Jensen

Різниця між ConvertAll і Select is 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.
користувач2864740

8
@ user2864740: Так, це правда, якщо джерело суворо є списком у пам'яті. Якщо він читається, наприклад, з файлу, то вам потрібно тримати файл відкритим, поки ви не обробите результат з Select.
Гуффа

19

Перша відповідь не повинна бути прийнятою. Я колишній MVP C # 2007 C # Microsoft.

На відміну від прийнятої відповіді, ConvertAllнабагато ефективніше, ніж комбінація Selectта ToList().

Перш за все, ConvertAllце суворо швидше, і для цього використовується мінімальний об'єм пам'яті. Те саме, що Array.ConvertAll vs Select та ToArray. Це було б набагато очевидніше, якщо масив більшої довжини або багато дзвінків всередині циклу.

1) ConvertAllзнає розмір остаточного списку і уникає перерозподілу базового масиву. ToList() буде змінювати розмір масиву кілька разів.

2) ToListбуде робити повільніші інтерфейсні IEnumerable<>дзвінки, в той час як ConvertAllбуде проходити через базовий масив без додаткових викликів або перевірки діапазону.

3) Вибір створить додатковий IEnumerable<T>об’єкт.


1

Я знаю, що це трохи пізно, але я все одно додав, тому що це може бути корисно для інших у майбутньому.

Під час використання його у виразі запиту EntityFramework не рекомендується використовувати ConvertAll (), оскільки він оцінює вираз, а не залишає його як вираз для подальшого використання. Це серйозно погіршує продуктивність виконання запитів до бази даних, оскільки йому доведеться здійснити кількість викликів, перш ніж оцінити остаточний вираз.


9
Не зовсім. Як в цій відповіді вказує Гуффа , ConvertAll це метод наList<T> . На той час, коли у вас є список, ви вже оцінили своє вираження. Але ти маєш рацію - якщо ти не хочеш оцінювати все, Selectто краще.
Вай Ха Лі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.