Чи повинен я використовувати два запитання “де” чи “&&” у своєму запиті LINQ?


76

Під час написання запиту LINQ з декількома умовами "і", чи слід писати один whereречення, що містить &&або кілька whereречень, по одному для кожного стану?

static void Main(string[] args)
{
    var ints = new List<int>(Enumerable.Range(-10, 20));

    var positiveEvensA = from i in ints
                         where (i > 0) && ((i % 2) == 0)
                         select i;

    var positiveEvensB = from i in ints
                         where i > 0
                         where (i % 2) == 0
                         select i;

    System.Diagnostics.Debug.Assert(positiveEvensA.Count() == 
                                         positiveEvensB.Count());
}

Чи існує якась різниця, крім особистих уподобань чи стилю кодування (довгі рядки, читабельність тощо) між positiveEvensA та positiveEvensB ?

Однією з можливих різниць, яка спадає на думку, є те, що різні постачальники LINQ можуть краще справлятися з множинними wheres, а не з більш складним виразом; це правда?

Відповіді:


53

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

У вашому випадку це, мабуть, взагалі не буде помітно, але наявність 2-х речень, безумовно, матиме вплив на продуктивність, якщо у вас велика колекція, і якщо ви використовуєте всі результати цього запиту. Наприклад, якщо ви викликаєте .Count () у результатах або перебираєте весь список, буде запущено перше речення where, створюючи нове IEnumerable <T>, яке буде повністю перераховано знову, з другим делегатом.

Об’єднання 2 речень разом призводить до того, що запит формує єдиний делегат, який запускається під час перерахування колекції. Це призводить до одного перерахування через колекцію та одного виклику делегатові кожного разу, коли результат повертається.

Якщо їх розділити, все змінюється. Оскільки ваше перше речення where перераховує вихідну колекцію, друге речення where перераховує його результати. Це спричиняє потенційно (найгірший випадок) 2 повні переліки у вашій колекції та 2 виклики делегатів на кожного члена, що може означати, що це твердження (теоретично) може зайняти вдвічі більшу швидкість виконання.

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

Тепер у вашому випадку це не матиме значення. На великій колекції це могло. Як загальне емпіричне правило, я вибираю:

  1. Читаність і ремонтопридатність

  2. Продуктивність

У цьому випадку я думаю, що обидва варіанти однаково ремонтопридатні, тому я б вибрав більш ефективний варіант.


38
З 2 реченнями "де" це все-таки лише одна ітерація з 2 викликами делегатів на елемент - а не 2 ітерації, як заявлено.
Марк Гравелл

5
Марк, коли я кажу дві ітерації, я мав би бути більш чітким. За допомогою речень 2 where ви ДОБАВТЕ побудувати два окремі перечислювачі - перший, де створюється перечислювач, який перераховується другим. Але це досить незначно - це не робити 2 цикли, а просто перераховувати за допомогою окремих перечислювачів.
Рід Копсі,

3
Я думаю, Whereє кілька спеціальних оптимізацій для випадку множинних пропозицій where. Однак це буде повільніше через багаторазові виклики делегатів.
CodesInChaos

21

Це здебільшого питання особистого стилю. Особисто, поки whereречення вміщується в одному рядку, я групую речення.

Використання декількох wheres, як правило, буде менш продуктивним, оскільки вимагає додаткового виклику делегата для кожного елемента, що робить його таким далеко. Однак це може бути незначною проблемою, і її слід розглядати лише в тому випадку, якщо профіліст показує, що це проблема.



1

Як припускають інші, це скоріше особисті переваги. Мені подобається використання &&, оскільки воно є більш читабельним і імітує синтаксис інших основних мов.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.