Select
І Where
методи доступні в Linq. Що повинен знати кожен розробник про ці два методи? Наприклад: коли використовувати один над іншим, будь-які переваги використання одного над іншим тощо.
Select
І Where
методи доступні в Linq. Що повинен знати кожен розробник про ці два методи? Наприклад: коли використовувати один над іншим, будь-які переваги використання одного над іншим тощо.
Відповіді:
Де
знаходить елементи, які відповідають, і повертає лише ті, що роблять ( фільтрація )
-> IEnumerable<A>
в, IEnumerable<A>
поза
Виберіть
повертає щось для всіх елементів джерела ( проекція / перетворення ). Це може бути самим предметом, але це, як правило, проекція якоїсь форми.
-> IEnumerable<A>
в, IEnumerable<B>
поза
Select
завжди буде повертати однакову кількість елементів у списку (незалежно від умови фільтра). Where
може повернути менше елементів залежно від стану вашого фільтра.
Where == filter
іSelect == map
Виберіть і Де є два абсолютно різні оператори, які діють на IEnumerable s.
Перший - це те, що ми називаємо Оператором проекції , а останній - Оператором обмеження .
Один цікавий спосіб зрозуміти поведінку таких операторів - поглянути на їх "функціональний тип".
Виберіть: (IEbroume <T1>, Func <T1, T2>) → IEnumerable <T2> ; він приймає як вхід як IE Число, що містить елементи типу T1, так і функцію, що перетворює елементи типу T1 в елементи типу T2. Вихід - IE численні елементи, що містять тип T2.
З цього можна легко здогадатися, що цей оператор буде виробляти свій результат, застосовуючи функцію введення на кожному елементі вхідного IEnumerable та обгортаючи результати всередині нового IEnumerable.
Використовуючи деякі математичні позначення, він приймає як вхідні дані (a, b, c, ...): IE Численні <T1> і f: T1 → T2 і виробляють (f (a), f (b), f (c) , ...): IE Численні <T2>
Де: (IE численні <T1>, Func <T1, bool>) → IEnumerable <T1> ; цей приймає IE численні елементи, що містять тип T1 і предикат на T1 (тобто функцію, яка створює бульний результат для вводу типу T1). Ви бачите, що вихід є також IEnumerable, що містить елементи типу T1.
Цього разу можна здогадатися, що елемент вхідного IEnumerable буде присутній на виході IEnumerable залежно від результату застосування присудка до елемента. Додавши до цього семантику імені оператора, ви можете бути впевнені, що він видасть вихід IEnumerable, беручи з вхідних даних лише ті елементи, які оцінюються як істинні в застосуванні предиката.
Люди з функціональним фоном програмування зазвичай думають так. Це дозволяє вивести (або принаймні здогадуватися ...), що робить оператор, лише переглянувши його тип!
Як вправу, спробуйте подивитися на інших операторів, представлених LINQ на IEnumerables, і виведіть їх поведінку, перш ніж переглянути документацію!
Вони відрізняються:
Select
все стосується трансформації .
Where
все стосується фільтрації .
Where
~ = Фільтр
Select
~ = Карта
Обидва повертаються IEnumerable<T>
Якщо ви знаєте, як вони реалізували Де і виберіть методи розширення, ви можете передбачити, що це робить ... Я спробував реалізувати, де і вибрати методи розширення ... Ви можете подивитися на це ...
Де реалізація ::
public static IEnumerable<Tsource> Where<Tsource> ( this IEnumerable<Tsource> a , Func<Tsource , bool> Method )
{
foreach ( var data in a )
{
//If the lambda Expression(delegate) returns "true" Then return the Data. (use 'yield' for deferred return)
if ( Method.Invoke ( data ) )
{
yield return data;
}
}
}
Вибрати реалізацію ::
public static IEnumerable<TResult> Select<TSource , TResult> ( this IEnumerable<TSource> a , Func<TSource , TResult> Method )
{
foreach ( var item in a )
{
//Each iteration call the delegate and return the Data back.(use 'yield' for deferred return)
yield return Method.Invoke ( item );
}
}
Моя реалізація чудово працює для будь-якої колекції ... Але вона відрізняється від методів розширення, впроваджених Майкросою, оскільки вони використовують дерева виразів, щоб реалізувати те саме.
У разі Select it ви можете зіставити IEnumerable нової структури.
A.Select(x=>new X{UID=x.uid, UNAME=x.uname})
//input as [IEnumerable<A>] --------> return output as [IEnumerable<X> ]
Там, де () працює як фільтр до IEnumerable, він поверне результат на основі пункту де.
A.Where(x=>x.uid!=0) //input as [IEnumerable<A>] --------> return output as [IEnumerable<A> ]